403 Forbidden Error with ajax GET request Spring
Solution 1
It is usually caused by Spring default CSRF protection.
If you use for example DELETE HTTP request from your JS code, it is required to send also CSRF protection headers.
It is not necessary to disable CSRF protection! Please, do not do that if not necessary.
You can easily add CSRF AJAX/REST protection by:
1.Adding meta headers to every page (use @layout.html or something):
<head>
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
</head>
2.Customizing your ajax requests to sent these headers for every request:
$(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);
});
});
Notice that i use thymeleaf, so i use th:content instead of content attribute.
Solution 2
If you are using Spring Security 3.2R1 and above try using this solution http://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection
Solution 3
As of Spring Security 4.0, CSRF protection is enabled by default with XML configuration. If you would like to disable CSRF protection, the corresponding XML configuration can be seen below.
<security:http use-expressions="true">
...
<security:csrf disabled="true" />
</security:http>
Solution 4
Check files permissions. 403 is server error, not Ajax. Try to check requested file (by file i mean url) directly.
Maff
Updated on July 24, 2022Comments
-
Maff almost 2 years
I am getting a
403 forbidden
-error every time I tryGET
a user's information from the database. Relating to my code below, every time I try request by pressing the Ajax Test button, It fails to run and gives me an alert, but also in the console gives me a403 Forbidden
-error. I am not sure whether it has something to do with Spring security?Users JSP page:
<table> <tr> <td>User Id</td> <td>Full Name</td> <td>Username</td> <td>Email</td> <td>Date of Birth</td> <td>User Authority</td> <td>Update </td> <td>Delete</td> </tr> <c:forEach var="user" items="${users}"> <tr> <td><c:out value="${user.id}" /></td> <td><c:out value="${user.name}"/></td> <td><c:out value="${user.username}"/></td> <td><c:out value="${user.email}"/></td> <td><c:out value="${user.dob}"/></td> <td><c:out value="${user.authority}"/></td> <td> <a id="update" href="<c:url value="/viewUser"><c:param name="id" value="${user.id}"/></c:url>"><button>Update</button></a> </td> <td> <a id="delete" href="<c:url value="/deleteUser"><c:param name="id" value="${user.id}"/></c:url>"><button>Delete</button></a> </td> <td> <button class="loadUser" name="id" value="${user.id}">Ajax test</button> </td> </tr> </c:forEach> </table> <div id="personIdResponse"> </div> <script type="text/javascript"> $(document).ready(function(){ $(".loadUser").click(function(e) { e.preventDefault(); var personId = +$(this).val(); $.get('${pageContext.request.contextPath}/SDP/ajaxTest/' + personId, function(user) { $('#personIdResponse').text(user.name + ', = username ' + user.username); }) .fail(function(user){ alert('Could not load user'); }); }); }); </script>
User Controller class:
@RequestMapping("/viewUser") public String updateUser(Model model, @RequestParam(value = "id", required = false) Integer id) { User user = usersService.getUser(id); model.addAttribute("user", user); return "settings"; } @RequestMapping("/ajaxTest") @ResponseBody public User ajaxTest(@RequestParam(value = "id", required = false) Integer id) { User user = usersService.getUser(id); return user; }
-
Maff over 10 yearsI just tried implementing this, but I got the exact same problem.
-
Maff over 10 years@RequestMapping(value="/ajaxTest/{personId}", method=RequestMethod.GET) @ResponseBody public User ajaxTest(@PathVariable Integer personId) { User user = usersService.getUser(personId); return user; } That is my update code in the controller.
-
harsh over 10 yearsCan you post your
rest-servlet.xml
as well? looks like by@ResponseBody
you are expectingjson
conversion, do you have havejackson
jar in classpath? not sure if this might be the case for403
forSpring REST
, but better to check.. -
harsh over 10 yearsAlso, what's your controller's
RequestMapping
url? -
Maff over 10 yearsI havn't got a rest-servlet.xml config file. I do have the jackson jar in the class path though.
-
harsh over 10 yearsWithout proper json conversion your req wouldn't succeed. Check json mapping configuration ibm.com/developerworks/library/wa-restful (listing-1), this should help.
-
Vineet Kasat over 10 years@Harsh If there is no matching resource at server side in Spring then 404 error is thrown, not 403. Also error codes have nothing to do with framework, it is tomcat dependent.
-
harsh over 10 yearsIt is not
tomcat
dependent at least in this case,404
is a sure case of not having matching resource (based onurl
) but403
can come if operation is not allowed (e.g. accept-type in request istxt
but at resource it is configured asjson
, this is one of a403
case and surely not404
) -
harsh over 10 years@VineetKasat My above comment is purely based on
REST
spec (jsr-311
) and implementation (in this caseSpring REST
) which has nothing to do with tomcat or any other web-server. -
Vineet Kasat over 10 years@Harsh 403 can come if request is broken. 403 means request has not reached server.
-
harsh over 10 yearsNot true (in some cases it may be), 403 in case is always sent either by
REST
container (i.e.Jersey
,Spring REST
) or by application code (i.e. apps authentication filter where on auth failureResponse.FORBIDDEN
is thrown, stackoverflow.com/a/6527453/878732).ResponseCode
javadoc jersey.java.net/nonav/apidocs/1.5/jersey/javax/ws/rs/core/… which is heavily used by application code to return specific status. -
zeleven over 6 yearsWhat is the
_csrf.headerName
? -
tomasz_kusmierczyk over 6 years@H.鄭 start trying with X-CSRF-TOKEN