27

I want to make a ajax call using $.POST. But I am getting 403 error. But GET works perfectly fine. My code is:

var url = "/xyz/abc/subscribe?name="+name;
$.post(url, function(data){
    alert(data);
});

The controller code is :

@RequestMapping(value = "/xyz/abc/subscribe", method = RequestMethod.POST)
public @ResponseBody
    String subscribe(@RequestParam("name") String name)
        throws Exception {
    String message = "TESTING";
    return message;
}

But I'm getting a 403 error.

gpgekko
  • 3,506
  • 3
  • 32
  • 35
user3729782
  • 271
  • 1
  • 3
  • 4
  • Do you have any error in the application server logs? – Luca Putzu Aug 06 '14 at 11:57
  • No...I did not find any error. – user3729782 Aug 06 '14 at 12:12
  • I am getting in logs: org.springframework.security.access.AccessDeniedException: Access is denied – user3729782 Aug 06 '14 at 13:40
  • 403 means that the server can correctly authenticate the user, but that the user does not have the appropriate rights to perform the selected operation. Are you using Spring security? If so, post the relevant configuration – geoand Aug 06 '14 at 14:05
  • I had the similar error and still it is not resolved http://stackoverflow.com/questions/25800657/bypass-spring-security-with-java-url-connection – pathfinder Sep 12 '14 at 15:31

5 Answers5

91

Using Spring Security with Java configuration, CSRF protection is enabled by default. In this context, if you make an Ajax request to a REST endpoint using POST method, you will get a csrf token missing error.

To solve this, there are two options:

Option 1: Disable csrf

@Override
protected void configure (HttpSecurity http) throws Exception {
    http.csrf().disable();
}

Option 2: Add csrf to the ajax request. See here

MD. Mohiuddin Ahmed
  • 2,092
  • 2
  • 26
  • 35
Emiliano Schiano
  • 1,862
  • 1
  • 25
  • 30
  • `@Override` of `configure` assumes your controller is a subclass of *what* type/class? – Don Cheadle Sep 24 '15 at 15:00
  • A sublcass of org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter – Emiliano Schiano Sep 24 '15 at 19:00
  • A must have glimpse at this:- 16.3 When to use CSRF protection When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection. SRC: http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#when-to-use-csrf-protection – 3AK May 22 '16 at 04:36
  • Check this out : http://stackoverflow.com/questions/27834867/spring-security-csrf-token-not-working-with-ajax/27836944#27836944 for how to put the csrf token through jquery-ajax. – 3AK May 22 '16 at 05:08
  • 3
    Worth highlighting that the Option 1. is not recommended as it can be risky. – Witold Kaczurba Feb 14 '17 at 21:42
  • I was writing a `POST` request using `requests` library in Python, and the `GET` method worked, while `POST` **didn't**. Disabling the CSRF protection solved the problem. Thank You! – Aleksandar May 26 '18 at 11:22
11

You might want to add the csrf token to the request.

Obtaining the token using JSTL should be pretty straightforward. If you are using Thymeleaf, here is how to obtain it.

<script th:inline="javascript">
    /*<![CDATA[*/
    var _csrf_token = /*[[${_csrf.token}]]*/ '';
    var _csrf_param_name = /*[[${_csrf.parameterName}]]*/ '';
    /*]]>*/
</script>

Then, add it to your request:

var requestData = {
    'paramA': paramA,
    'paramB': paramB,
};
requestData[_csrf_param_name] = _csrf_token; // Adds the token

$.ajax({
    type: 'POST',
    url: '...your url...',
    data: requestData,
    ...
});

If everything goes well, the request should include something like _csrf:1556bced-b323-4a23-ba1d-5d15428d29fa (the csrf token) and you will get a 200 instead of a 403.

izilotti
  • 4,757
  • 1
  • 48
  • 55
  • This helps, but only if I change `csrf_param_name` to `csrf`. How do you know the name to use for the variable ? – HelloWorld Mar 21 '22 at 04:54
6

This is an example of without disabling CSRF.

Step 1: In your header add CSRF like this

<meta th:name="${_csrf.parameterName}" th:content="${_csrf.token}"/>

Step 2: Make call with token

$( "#create_something" ).click(function() {

  var token = $("meta[name='_csrf']").attr("content");

  $.ajax({
    url : '/xxxxxxxxxxxx', // url to make request
    headers: {"X-CSRF-TOKEN": token}, //send CSRF token in header
    type : 'POST',
    success : function(result) {
        alert(result);
    }
  })
});
VK321
  • 5,768
  • 3
  • 44
  • 47
0

If you look to CSRFilter source code, you will see that the filter is waiting for csrfToken on header or query parameter. In my configuration, the key "_csrf" was the right key in query parameter. So, I added this parameter in my post call.

      var csrfCookie = getCsrfCookie();
      alert(csrfCookie);
      
     function getCsrfCookie()
     {
      var ret = "";
      var tab = document.cookie.split(";");
      
      if(tab.length>0){
       var tab1 = tab[0].split("=");
       if(tab1.length>1)
       {
        ret =tab1[1];
       }
      }
      return ret;
     }
     
     $http.post('/testPost?_csrf='+csrfCookie).success(function (response) {
             alert("post : "+response);
              return response;
          });

With this, it works for me.

BenoitJ
  • 19
  • 1
-3

You're trying to make a POST request to a REST endpoint you're not authorized to. Either your session has become invalid, or the user you're logging in as doesn't have authority like @geoand already pointed out.

Patrick Grimard
  • 7,033
  • 8
  • 51
  • 68