I am working on a Laravel 5 app that has CSRF protection enabled by default for all POST requests. I like this added security so I am trying to work with it.
While making a simple $.post()
request I received a 'Illuminate\Session\TokenMismatchException'
error because the required form input _token
was missing from the POST data. Here is an example of a $.post request in question:
var userID = $("#userID").val();
$.post('/admin/users/delete-user', {id:userID}, function() {
// User deleted
});
I have my CSRF token stored as a meta field in my header and can easily access it using:
var csrf_token = $('meta[name="csrf-token"]').attr('content');
Is it possible to append this to the json data on all outgoing $.post()
requests? I tried using headers but Laravel did not seem to recognize them -
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);
}
});
I think that above solution might not work as well. When you do:
You will get data like "undefined_token=xxx"
When you use the above solution for laravel's delete for instance you have to check like this:
Generally I agree with the concept Kornel suggested except one thing.
Yes, Laravel's docs advice to use
$.ajaxSetup
, but it's not recommended since this method affects all the subsequent ajax requests. It is more correctly to set the ajax settings for each request. Though you can re-set stuff:If you use
$.ajax()
, it's more convenient to utilize eitherdata
property orheaders
. Laravel allows CSRF-token both as a request parameter or a header.First, you add the following meta tag into the view
And then make an ajax request either way:
OR
there is a much easier method to do this you can serialize the data like so before sending
everything with a name attr will be put in to a query and submited
From Laravel documentation:
So for example you can do request like below.
Add this meta tag to your view:
And this is an example script which you can communicate with Laravel (sends request when you click an element with id="some-id" and you can see the response in an element with id="result"):
Your
$.ajaxPrefilter
approach is a good one. You don't need to add a header, though; you simply need to add a property to thedata
string.Data is provided as the the second argument to
$.post
, and then formatted as a query string (id=foo&bar=baz&...
) before the prefilter gets access to thedata
option. Thus, you need to add your own field to the query string:This will turn
id=userID
intoid=userID&_token=csrf_token
.The Django documentation on CSRF gives a nice code snippet with
ajaxSetup
for automatically adding the appropriate header to all request types where it matters: