por - jQuery añade token CSRF a todos los datos de las solicitudes $.post()
laravel post (5)
Creo que la solución anterior podría no funcionar tan bien. Cuando tu lo hagas:
var x;
x + ""
// "undefined" + empty string coerces value to string
Obtendrás datos como "undefined_token = xxx"
Cuando utilizas la solución anterior para eliminar laravel, por ejemplo, tienes que marcar de esta manera:
if (typeof options.data === "undefined")
options.data = "";
else
options.data += "&";
options.data = "_token=" + csrf_token;
Estoy trabajando en una aplicación Laravel 5 que tiene habilitada la protección CSRF por defecto para todas las solicitudes POST. Me gusta esta seguridad adicional, así que estoy tratando de trabajar con ella.
Al realizar una solicitud $.post()
simple recibí un error ''Illuminate/Session/TokenMismatchException''
porque la entrada de formulario requerida _token
faltaba en los datos POST. Aquí hay un ejemplo de una solicitud de $ .post en cuestión:
var userID = $("#userID").val();
$.post(''/admin/users/delete-user'', {id:userID}, function() {
// User deleted
});
Tengo mi token CSRF almacenado como un meta campo en mi encabezado y puedo acceder fácilmente usando:
var csrf_token = $(''meta[name="csrf-token"]'').attr(''content'');
¿Es posible agregar esto a los datos json en todas las solicitudes salientes $.post()
? Intenté usar encabezados, pero Laravel no pareció reconocerlos.
var csrf_token = $(''meta[name="csrf-token"]'').attr(''content'');
alert(csrf_token);
$.ajaxPrefilter(function(options, originalOptions, jqXHR){
if (options[''type''].toLowerCase() === "post") {
jqXHR.setRequestHeader(''X-CSRFToken'', csrf_token);
}
});
Su enfoque $.ajaxPrefilter
es bueno. No es necesario agregar un encabezado, sin embargo; simplemente necesita agregar una propiedad a la cadena de data
.
Los datos se proporcionan como el segundo argumento para $.post
, y luego formateados como una cadena de consulta ( id=foo&bar=baz&...
) antes de que el prefiltro acceda a la opción de data
. Por lo tanto, debe agregar su propio campo a la cadena de consulta:
var csrf_token = $(''meta[name="csrf-token"]'').attr(''content'');
$.ajaxPrefilter(function(options, originalOptions, jqXHR){
if (options.type.toLowerCase() === "post") {
// initialize `data` to empty string if it does not exist
options.data = options.data || "";
// add leading ampersand if `data` is non-empty
options.data += options.data?"&":"";
// add _token entry
options.data += "_token=" + csrf_token;
}
});
Esto convertirá id=userID
en id=userID&_token=csrf_token
.
De la documentación de Laravel:
Podría, por ejemplo, almacenar el token en una etiqueta "meta":
Una vez que haya creado la metaetiqueta, puede instruir a una biblioteca como jQuery para que agregue el token a todos los encabezados de solicitud. Esto proporciona una protección CSRF simple y conveniente para sus aplicaciones basadas en AJAX:
$ .ajaxSetup ({headers: {''X-CSRF-TOKEN'': $ (''meta [nombre = "csrf-token"]''). attr (''contenido'')}});
Entonces, por ejemplo, puede hacer la solicitud como a continuación.
Agregue esta metaetiqueta a su vista:
<meta name="csrf-token" content="{{ csrf_token() }}">
Y este es un script de ejemplo que puede comunicar con Laravel (envía una solicitud cuando hace clic en un elemento con id = "some-id" y puede ver la respuesta en un elemento con id = "resultado"):
<script type="text/javascript">
$(document).ready(function(){
$.ajaxSetup({
headers:
{ ''X-CSRF-TOKEN'': $(''meta[name="csrf-token"]'').attr(''content'') }
});
$("#some-id").on("click", function () {
var request;
request = $.ajax({
url: "/your/url",
method: "POST",
data:
{
a: ''something'',
b: ''something else'',
},
datatype: "json"
});
request.done(function(msg) {
$("#result").html(msg);
});
request.fail(function(jqXHR, textStatus) {
$("#result").html("Request failed: " + textStatus);
});
});
});
</script>
En general, estoy de acuerdo con el concepto que Kornel sugirió excepto una cosa.
Sí, los consejos de Laravel docs para usar $.ajaxSetup
, pero no se recomienda ya que este método afecta todas las solicitudes ajax subsiguientes. Es más correcto establecer las configuraciones de Ajax para cada solicitud. Aunque puedes volver a configurar cosas:
Todas las llamadas Ajax subsiguientes que usen cualquier función usarán la nueva configuración, a menos que sean anuladas por las llamadas individuales, hasta la próxima invocación de $ .ajaxSetup ()
Si usa $.ajax()
, es más conveniente utilizar propiedades de data
o headers
. Laravel permite CSRF-token como un parámetro de solicitud o un encabezado.
Primero, agregue la siguiente metaetiqueta en la vista
<meta name="csrf-token" content="{{ csrf_token() }}">
Y luego haz una solicitud de AJAX de cualquier forma:
$.ajax({
url: "/your/url",
method: "POST",
data:
{
a: ''something'',
b: ''something else'',
_token: $(''meta[name="csrf-token"]'').attr(''content'')
},
datatype: "json"
});
O
$.ajax({
url: "/your/url",
method: "POST",
data:
{
a: ''something'',
b: ''something else'',
},
headers:
{
''X-CSRF-TOKEN'': $(''meta[name="csrf-token"]'').attr(''content'')
}
datatype: "json"
});
La documentación de Django en CSRF brinda un buen fragmento de código con ajaxSetup
para agregar automáticamente el encabezado apropiado a todos los tipos de solicitud donde sea importante:
function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });