Reputation: 3328
I'm using Spring Security with CSRF and I have a problem with some POST call in my javascript. For my page I use Thymeleaf and HTML 5, for the Rest call to my controller I use jQuery.ajax. If I use the ajax call for my form like this:
$(function() {
$("#saveCarButton").click(
function() {
var form = $("#addCarForm");
$.ajax({
type : "POST",
url : form.attr("action"),
data : form.serialize(),
// all right with rest call
success : function(data) {...}
//error during rest call
error : function(data) {
window.location.href = "/500";
}
});
});
});
everything works fine, but when I call for example this function:
jQuery.ajax({
url : 'upload',
type: 'POST',
contentType: false,
processData: false,
data:formData,
beforeSend:function(xhr) {
waitingModal.showPleaseWait();
},
success: function(data,status,xhr){...}
error: function(xhr,status,e){
}
}).complete(function() {
//add timeout because otherwise user could see a too fast waiting modal
setTimeout(function(){
waitingModal.hidePleaseWait();
}, 1000);
});
I receive error 403. Maybe with form, using thymeleaf, it works fine but with the second type of request I have to add CSRF token. I tried with
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
and in my html page I added
!-- -->
<meta name="_csrf" th:content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
Why does it with the form work? I don't have to add nothing when I use form? Is it danger that _csrf and _csrf_header are visible with dev tool of browser? thanks
Upvotes: 13
Views: 10887
Reputation: 829
This solution worked for me Trying to use React/Ajax calls with Spring MVC and Thymeleaf
<meta id="_csrf" name="_csrf" th:content="${_csrf.token}"/>
<meta id="_csrf_header" name="_csrf_header" th:content="${_csrf.headerName}"/>
Ajax:
var token = $('#_csrf').attr('content');
var header = $('#_csrf_header').attr('content');
$.ajax({
type: "POST",
url: url,
beforeSend: function(xhr) {
xhr.setRequestHeader(header, token);
},
success: function(data, textStatus, jqXHR) {
alert(status);
},
error: function(request, status, error) {
alert(status);
}
});
Upvotes: 17
Reputation: 8434
This is most likely due to the fact no CSRF token is being sent through hence the 403.
This is the fix that does the trick for these sorts of things (at least for me).
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 summary it attaches the CSRF token to any post request you do via ajax.
Upvotes: 9