How to pass CSRF token in AJAX mail request for form?

I am using Scala Play! 2.6, but this may not be a problem. I use their Javascript routing - and it seems to work fine, but it has problems. I have a form that renders this using the CSRF token:

<form method="post" id="myForm" action="someURL"> <input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden"> <input type="text" id="sometext"> <button type="submit"> Submit! </button> </form> 

And here's about, my AJAX:

 $(document).on('submit', '#myForm', function (event) { event.preventDefault(); var data = { textvalue: $('#sometext').val() } var route = jsRoutes.controllers.DashboardController.postNewProject() $.ajax({ url: route.url, type: route.type, data : JSON.stringify(data), contentType : 'application/json', success: function (data) { ... }, error: function (data) { ... } }) }); 

But when I send this message, I get a UNAUTHORIZED response from my server, and my console in IntelliJ tells me that the CSRF check does not work. How would I skip the CSRF token in the request?

+11
source share
6 answers

Well, after several hours of fighting this and trying to decipher the documentation of the often-missing context on the topic , I understood.

So from their docs:

To provide simple protection for requests not from the browser, Play only checks requests with cookies in the header. If you are making requests with AJAX, you can put the CSRF token on the HTML page and then add it to the request using the Csrf-Token header.

And there is no code, no example. Thanks Play. Very clear. Anyway, here's how:

in your view.html.formTemplate you can write in IntelliJ:

 @() <form method="post" id="myForm" action="someURL"> @helper.CSRF.formField <!-- This auto-generates a token for you --> <input type="text" id="sometext"> <button type="submit"> Submit! </button> </form> 

And it will look like this when delivered to a customer:

 <form method="post" id="myForm" action="someURL"> <input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden"> <input type="text" id="sometext"> <button type="submit"> Submit! </button> </form> 

Ok, almost there, now we have to create our AJAX call. I have everything in a separate main.js file, but you can also put this in your view.html.formTemplate if you want.

 $(document).on('submit', '#myForm', function (event) { event.preventDefault(); var data = { myTextToPass: $('#sometext').val() } // LOOK AT ME! BETWEEN HERE AND var token = $('input[name="csrfToken"]').attr('value') $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('Csrf-Token', token); } }); // HERE var route = jsRoutes.controllers.DashboardController.postNewProject() $.ajax({ url: route.url, type: route.type, data : JSON.stringify(data), contentType : 'application/json', success: function (data) { ... }, error: function (data) { ... } }) }); 

With this line: var token = $('input[name="csrfToken"]').attr('value') You retrieve the CSRF token automatically generated in the form field and capture its value in the variable that will be used in your Javascript

Another important piece of everything that is in AJAX:

 $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('Csrf-Token', token); } }); 

Using $.ajaxSetup , you can set that in the header. Here is what you should do from their documentation:

add it to the request using the Csrf-Token header.

Good luck Let me know if this is clear.


Note : when using lusca, use X-CSRF-Token instead of Csrf-Token .

+18
source

add it to the request using the Csrf-Token header.

Thanks to NateH06 for the title name! I tried to send the csrf token for the delete button with the ajax function call, and I was stuck with the following:

 @import helper._ .... <button id="deleteBookBtn" class="btn btn-danger" data-csrf-name="@helper.CSRF.getToken.name" data-csrf-value="@helper.CSRF.getToken.value" data-delete-url="@routes.BooksController.destroy(book.id)" data-redirect-url="@routes.HomeController.index()">Delete</button> 

I was unable to add online js to the onclick() event due to the installation of CSP in game 2.6.

The embedded event handler was denied execution because it violates the following content security policy directive: "default-src" self ".

And in the JS file:

 function sendDeleteRequest(event) { url = event.target.getAttribute("data-delete-url") redirect = event.target.getAttribute("data-redirect-url") csrfTokenName = event.target.getAttribute("data-csrf-name") csrfTokenValue = event.target.getAttribute("data-csrf-value") $.ajax({ url: url, method: "DELETE", beforeSend: function(request) { //'Csrf-Token' is the expected header name, not $csrfTokenName request.setRequestHeader(/*$csrfTokenName*/'Csrf-Token', csrfTokenValue); }, success: function() { window.location = redirect; }, error: function() { window.location.reload(); } }) } var deleteBookBtn = document.getElementById("deleteBookBtn"); if(deleteBookBtn) { deleteBookBtn.addEventListener("click", sendDeleteRequest); } 

After setting the header name as 'Csrf-Token' ajax call works fine!

+2
source

From JSP

 <form method="post" id="myForm" action="someURL"> <input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden"> </form> 

This is the easiest way that worked for me after a fight for 3 hours, just get a token from a hidden input field like this, and when executing an AJAX request, you just need to transfer this token to the header as follows: -

From jquery

 var token = $('input[name="csrfToken"]').attr('value'); 

From plain Javascript

 var token = document.getElementsByName("csrfToken").value; 

Final AJAX request

 $.ajax({ url: route.url, data : JSON.stringify(data), method : 'POST', headers: { 'X-CSRF-Token': token }, success: function (data) { ... }, error: function (data) { ... } 

});

Now you do not need to disable crsf protection in the web configuration, and this will not lead to a 405 error (method is not allowed) on the console.

Hope this helps people .. !!

+1
source

You can add a Csrf-Token header with the headers parameter.

 $.ajax({ url: '@routes.MyController.myPostAction()', method: 'post', headers: { 'Csrf-Token': '@play.filters.csrf.CSRF.getToken.map(_.value)' }, data: { name: '@name' }, success: function (data, textStatus, jqXHR) { location.reload(); }, error: function (jqXHR, textStatus, errorThrown) { debugger; } }); 
0
source

As stated in the Play Framework 2.6 documentation, you can set the Csrf-Token header with the token generated by the Play:

If you make requests using AJAX, you can put the CSRF token on the HTML page and then add it to the request using the Csrf-Token header.

In Scala-Template, you can get the value of the token using @helper.CSRF.getToken.value

Following the jQuerys documentation , you can install it once for all Ajax requests by configuring jQuery with ajaxSetup

 $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('Csrf-Token', '@helper.CSRF.getToken.value'); } }); 

or alternatively set a header for each request by setting up the headers object as follows:

 $.ajax({ url: route.url, ... headers: { 'Csrf-Token': '@helper.CSRF.getToken.value' } }); 
0
source

In case it is useful to everyone who searches on Google, trying to understand why they can’t get the correct token .... I struggled with the same problem for the Play backend / React combination - and, therefore, unable to (easily) use the technique token-in-htmlpage, I eventually came across another solution to set the current token in a cookie ... just add:

 play.filters.csrf { cookie.name = "csrftoken" } 

to application.conf, and the csrftoken cookie will be set to the token. Then I used https://www.npmjs.com/package/js-cookie to get the value in my JS code and send it back to the request header - not counting the code here, since it is not responding to jQuery, as for OP, and does not want to confuse the questions.

0
source

Source: https://habr.com/ru/post/1270508/


All Articles