Reputation: 626
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
Upvotes: 16
Views: 18759
Reputation: 1957
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}"/>
Upvotes: 4
Reputation: 626
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.
Upvotes: 20
Reputation: 5832
You can set the Spring Security's CSRF Token into a Javascript variable called MyApp.csrfToken
.
In your JSP, add the flowing script to call the init function once your document is ready:
<script type="text/javascript">
document.onreadystatechange = function () {
var state = document.readyState;
if (state == 'complete') {
fnInit("${_csrf.parameterName}", "${_csrf.token}");
}
};
</script>
In your JS file, define the fnInit
function
var MyApp = MyApp || {};
function fnInit(csrfParam, csrfToken) {
MyApp.csrfToken = {
param : csrfParam,
value : csrfToken
}
}
Now you have the token ready to use in any ajax call
...
...
xhttp.open("POST", "http://localhost:8080/bids?q="+selected + "&"+ MyApp.csrfToken.param+"="+ MyApp.csrfToken.value, true);
xhttp.send();
PS: No need for jQuery, it is pure JavaScript.
Upvotes: 0
Reputation: 36179
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);
});
});
Upvotes: 13
Reputation: 1424
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();
Upvotes: 3
Reputation: 101
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);
});
Upvotes: 2