Reputation: 2370
I have a problem in my spring boot app with the csrf token.
I have a form where I can edit a Person. A Person can have
Let us now imagine that the person has a car and enter this and store it. The next time he wants to delete this car and enter another one. I have created that so that there is a list of all of his cars -- he has the option to remove this from the list. Now I'm starting from these pills and want to send with the corresponding ID to the server a POST. When I try I get a 403 forbidden and I have no idea why.
If I change from POST to GET, then it works.
My JavaScript (taken from this site: http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag)
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
// using JQuery to send a non-x-www-form-urlencoded request
var headers = {};
headers[csrfHeader] = csrfToken;
$.ajax({
url: "./delete/car",
type: "GET",
headers: headers,
});
$.ajax({
url: "./delete/car",
type: "POST",
headers: headers,
});
My controller methods:
@RequestMapping(value = "/{login}/delete/car", method = RequestMethod.GET)
public ModelAndView delete(@PathVariable("login") final String login) {
System.out.println("Stop");
return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
}
@RequestMapping(value = "/{login}/delete/car", method = RequestMethod.POST)
public ModelAndView deleteInstEmp(@PathVariable("login") final String login) {
System.out.println("Stop");
return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
}
Any suggestions?
Thanks in advance.
Upvotes: 7
Views: 21141
Reputation: 1334
I suggest you first check if a valid csrf token and the header have been generated using chrome debugger. If not, then have you added the <sec:csrfMetaTags />
in the <head>
?(you will need to import the spring security taglibs). If using Apache tiles, you will have to add this at the <head>
section of the template file being used for the view.
If the token is not empty, then in your security-context/configuration file, check if you have disabled csrf security by any chance. By default it is enabled and needs to be for this process to work.
Upvotes: 0
Reputation: 591
Another way, you can use the following code:
$.ajax({
url : './delete/car',
headers: {"X-CSRF-TOKEN": $("input[name='_csrf']").val()},
type : 'POST',
success : function(result) {
alert(result.msgDetail);
}
})
Upvotes: 4
Reputation: 2370
OK, after strugglin with all that, I get the following result.
I added the fail
method to the Ajax construct and get the following message:
"Failed to execute 'setRequestHeader' on 'XMLHttpRequest': '${_csrf.headerName}' is not a valid HTTP header field name."
the official spring site advises that you have to put this: <sec:csrfMetaTags />
or from other sources, this: <meta name="_csrf" th:content="${_csrf.token}"/>
in your html file.
After this, you should be able to access these attributes in your JavaScript, but in my case I get undefined
and ${_csrf.headerName}
.
A last try was to take the value from the hidden value (chapter 24.5: http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag).
Now, I have the following:
$(function () {
var token = $("input[name='_csrf']").val();
var header = "X-CSRF-TOKEN";
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$.ajax({
url: "./delete/car",
type: "POST",
success:function(response) {
alert(response);
}
});
With this it works like a charm.
Upvotes: 20