I have issues adding csrf to ajax request. I'm using thymeleaf on client side with spring-boot/spring security. Spring security wouldn't allow the request because csrf-token is missing. Here is my code for ajax
function bits(){
var xhttp = new XMLHttpRequest();
var selected = document.getElementById("product").value;
xhttp.onreadystatechange = function(){
if(xhttp.readyState==4 && xhttp.status==200){
var result= JSON.parse(xhttp.responseText)
var length = result.length;
for(i=0; i<length; i++){
console.log(result[k].spid);
}
}
};
xhttp.open("POST", "http://localhost:8080/bids?q="+selected, true);
xhttp.send();
}
Help will be appreciated
CSRF tokens are secrets and should be handled as such in a secure manner throughout their lifecycle. Place the field containing the CSRF token as early as possible within the HTML file. Place the field that contains the token before any non-hidden fields and before any places where user-controllable data is embedded.
The client acquires a new CSRF token from the server by calling the REST endpoint baseURL/v1/csrf/tokens. The server generates a new, unique CSRF token and sends the token to the client in a custom HTTP response header.
I modified @Prakash Hari Sharma's solution and had the following code that worked for me. Note, th: prefix if using Thymeleaf.
--Header section
<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>
Ajax script function
...
...
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
...
...
xhttp.open("POST", "http://localhost:8080/bids?q="+selected, true);
xhttp.setRequestHeader(header, token);
xhttp.send();
Hope this helps someone too.
As a complementary to @EdwardoS answer, after you add meta tags to the <head>
element:
Thymeleaf:
<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>
JSP:
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
...you can then do what is suggested in Spring documentation and have all your future ajax to include csrf
:
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function (e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
In spring documentation, it is also suggested that you do not use csrf token in GET requests for security reasons
"The ability to scope which requests receive the token helps guard against leaking the CSRF token to a third party."
You can therefore filter to pass token only for POST requests with following manner:
$(function() {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
if (options.type == "POST") {
xhr.setRequestHeader(header, token);
}
});
});
The meta tags in <head>
element would be the same as in previous answers:
<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>
Store CSRF Token in your jsp meta tags
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
and add values of csrf token in ajax request
var elementToken = document.querySelector('meta[property="_csrf"]');
var token = elementToken && elementToken.getAttribute("content");
var elementHeader = document.querySelector('meta[property="_csrf_header"]');
var header = elementHeader && elementHeader.getAttribute("content");
xhttp.open("POST", "http://localhost:8080/bids?q="+selected, true);
xmlhttp.setRequestHeader(header, token);
xhttp.send();
below you can find my code to use ajax with csrf. I use Spring Security too.
// In your JSP meta tags
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
// In your javascript
// CSRF Variables
var _tc = $("meta[name='_csrf']").attr("content");
var _hc = $("meta[name='_csrf_header']").attr("content");
// Header
var headersStomp = {};
headersStomp[_hc] = _tc;
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(_hc, _tc);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With