jQuery add CSRF token to all $.post() requests' data
From Laravel documentation:
You could, for example, store the token in a "meta" tag:
Once you have created the meta tag, you can instruct a library like jQuery to add the token to all request headers. This provides simple, convenient CSRF protection for your AJAX based applications:
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });
So for example you can do request like below.
Add this meta tag to your view:
<meta name="csrf-token" content="{{ csrf_token() }}">
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"):
<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>
Your $.ajaxPrefilter
approach is a good one. You don't need to add a header, though; you simply need to add a property to the data
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 the data
option. Thus, you need to add your own field to the query string:
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=" + encodeURIComponent(csrf_token); }});
This will turn id=userID
into id=userID&_token=csrf_token
.
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:
All subsequent Ajax calls using any function will use the new settings, unless overridden by the individual calls, until the next invocation of $.ajaxSetup()
If you use $.ajax()
, it's more convenient to utilize either data
property or headers
. Laravel allows CSRF-token both as a request parameter or a header.
First, you add the following meta tag into the view
<meta name="csrf-token" content="{{ csrf_token() }}">
And then make an ajax request either way:
$.ajax({ url: "/your/url", method: "POST", data: { a: 'something', b: 'something else', _token: $('meta[name="csrf-token"]').attr('content') }, datatype: "json"});
OR
$.ajax({ url: "/your/url", method: "POST", data: { a: 'something', b: 'something else', }, headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } datatype: "json"});