سؤال

AngularJS authenticates against server side using REST, and gets the JSESSIONID cookie. In the next step I am trying to get some JSON data from server side using REST along with the session cookie gained in the previous step. Here is the client-side code:

getSomeJSONDataFromServer:function() {
var deferred = $q.defer();
$http({
    method: 'POST',
    withCredentials: true,
    url: "http://domain.name/app/someURL",
    headers:{
        'Accept':'application/json',
        'Content-Type':'application/json; charset=utf-8',
        'Access-Control-Request-Headers': 'X-Requested-With, content-type, accept, origin, withcredentials'
    }
})
.success(function(data, status, headers, config) {
    // handle data
})
.error(function(data, status, headers, config) {
    // handle error
});
return deferred.promise;
}

The code above works OK:

CORS $http request without body

The problems start when I send some data in the above POST request body.

...
$http({
    method: 'POST',
    withCredentials: true,
    url: "http://domain.name/app/someURL",
    headers:{
        'Accept':'application/json',
        'Content-Type':'application/json; charset=utf-8',
        'Access-Control-Request-Headers': 'X-Requested-With, content-type, accept, origin, withcredentials'
    },
    data: '{}'
})
.success(...

The above code fails in the prelight request:

CORS $http request with body fails!

Looks like the server starts a new session because the session cookie is not sent for some reason. Anyway, I feel like I am missing something really simple, some header or something like that... Any ideas are appreciated. Thanks in advance.

هل كانت مفيدة؟

المحلول 2

According to Cross-Origin Request with Preflight specs credentials, i.e. session cookie, is not sent within the preflight request, therefore the solution is to disable security on OPTIONS requests on your REST server side and allow requests without session cookie only for OPTIONS requests.

Of course be careful to not disable security for POST and GET requests.

نصائح أخرى

Amir,

Allow me to help you and others clearly understand what is expected when dealing with CORS, as such:

Index:

  • Simple CORS Version
  • Preflighted CORS version
  • Requests with Credentials

Simple CORS Version

  1. You can use GET, HEAD or POST:
    • In any of the method cases, you CANNOT set custom headers.
    • You can always have the server side restrict domain access through Access-Control-Allow-Origin header.
  2. And if POST has request data:
    • Content-Type MUST BE either of the followings:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/html

This SIMPLE version clearly IS NOT your case...

Preflighted CORS Version

  1. You can use GET, HEAD or POST:
    • In any of the method cases, you CAN set custom headers.
    • You can always have the server side restrict domain access through Access-Control-Allow-Origin header.
  2. And if POST has request data:
    • Content-Type MAY BE of the followings:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/html
    • Content-Type CAN ALSO BE of other types:
      • application/json
      • application/xml
      • text/xml
      • etc.

This PREFLIGHTED version clearly IS your case...

Requests with Credentials

  1. If your invoking calls with cookies, you need to set the following parameter part of your request:
    • withCredentials = true

Requests with Credentials clearly IS your case as well...

According to https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

In order to allow cookie in the POST, need configure the remote with the Access-Control-Allow-Credentials: true.

If you are using jetty, you need configure the

    <init-param>
        <param-name>allowCredentials</param-name>
        <param-value>true</param-value>
    </init-param>

And quote from MDN article,

Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example, the credential-cognizant content is returned to the invoking web content.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top