I'm trying to make an ajax call to my Spring controller/action with POST method, and return an object from the server with @ResponseBody. The strange situation is that it stop working after add spring security layer, everything was working fine before. I will try to explain my moves to solve the problem and then show you the code/captures/etc.
1. After some research I found some answers telling the problem might be related with csrf mechanism, so I disabled it and still have the issue. (spring-security.xml bellow)
2. I've made a wireshark capture to check the request/response. My ajax request is OK, my controller declaration is OK, but I don't understand why, the 405 response indicates > Allow: GET (capture bellow)
3. I've tried to access my controller action through the browser (i.e., make an GET request), and I get the error HTTP Status 405 - Request method 'GET' not supported!
4. I've tried to change the RequestMapping(method...) to RequestMethod.GET and the request arrives to the controller and works fine, but I don't want it to work on GET method, I want a POST request.
5. Changed the RequestMapping(consumes, produces, headers) to accept all kind of data, but still 405...
This is driving me crazy! I post my files bellow, so you can check it guys, any tip will be appreciated. Thanks! (IMPORTANT NOTE: this is my despair configuration)
spring-security.xml
<beans:beans
xmlns...(all needed declarations)>
<http pattern="/js/**" security="none" />
<http pattern="/css/**" security="none" />
<!-- enable use-expressions -->
<http auto-config="true" >
<access-denied-handler error-page="/403" />
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/login" access="isAnonymous()" />
<intercept-url pattern="/403" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login"
username-parameter="email"
password-parameter="password"
authentication-failure-url="/login?failed" />
<!--
<csrf/>
-->
</http>
..... (authentication)
AdminController.java
@Controller
@RequestMapping("/admin**")
public class AdminController {
... (all my autowired beans)
@RequestMapping(
value = "/events/loadEvents",
method = RequestMethod.POST,
consumes = MediaType.ALL_VALUE,
produces = MediaType.ALL_VALUE,
headers = "Accept=*/*")
@ResponseBody
public Event loadEvents(@RequestParam("parentId") long parentId) {
... (my logic)
return event;
}
}
EDIT jquery ajax call code
$.ajax({
type: 'POST',
cache: false,
url: /admin/events/loadEvents,
data: { parentId: 1 },
dataType = 'json',
contentType = 'application/json',
...
});
After many hours of research and tests, I finally got it, ant it was a (very very) stupid situation. So, in my question I said
so I disabled it (csrf on spring-security.xml) and still have the issue.
No, I didn't disabled it. I was trying to disable it doing
<!--
<csrf/>
-->
But I should be doing:
<csrf disabled="true"/>
Commenting csrf tag does NOT disable csrf, this is because csrf is enabled by default! After find the problem is really easy to say that is a stupid mistake, but as I added csrf tag to enable it, I thought that commenting it would disable it. Find the answer on Spring Documentation
Now, back into my problem. To fix the 405 error message in a POST AJAX call WITH CSRF ENABLED, it was really easy. I keep the csrf parameters in JS variables like this:
<script type="text/javascript">
var csrfParameter = '${_csrf.parameterName}';
var csrfToken = '${_csrf.token}';
</script>
and then my ajax call looks like this:
var jsonParams = {};
jsonParams['parentId'] = 1;
jsonParams[csrfParameter] = csrfToken;
$.ajax({
type: 'POST',
cache: false,
url: /admin/events/loadEvents,
data: jsonParams,
dataType = 'json',
contentType = 'application/json',
...
});
Working like a charme. Hope that helps someone in the future.