AngularJS $http POST withCredentials не работает с данными в теле запроса

AngularJS аутентифицируется на стороне сервера с помощью REST и получает файл cookie JSESSIONID. На следующем шаге я пытаюсь получить некоторые данные JSON со стороны сервера, используя REST вместе с файлом cookie сеанса, полученным на предыдущем шаге. Вот код на стороне клиента:

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;
}

Приведенный выше код работает нормально:

CORS $http-запрос без тела

Проблемы начинаются, когда я отправляю некоторые данные в приведенном выше теле запроса POST.

...
$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(...

Приведенный выше код не работает в предварительном запросе:

Ошибка запроса CORS $http с телом!

Похоже, что сервер запускает новый сеанс, потому что файл cookie сеанса по какой-то причине не отправляется. Во всяком случае, я чувствую, что мне не хватает чего-то очень простого, какого-то заголовка или чего-то в этом роде... Любые идеи приветствуются. Заранее спасибо.


person Amir Jamak    schedule 13.03.2014    source источник
comment
Кажется, это проблема междоменного вызова. Вызовы AJAX отправляют файлы cookie только в том случае, если URL-адрес, по которому вы звоните, находится в том же домене, что и ваш вызывающий скрипт.   -  person Vaibhav Jain    schedule 13.03.2014
comment
Да, определенно это вызов CORS. И это работает, пока вы не добавите тело к запросу...   -  person Amir Jamak    schedule 13.03.2014


Ответы (3)


Амир,

Позвольте мне помочь вам и другим четко понять, что ожидается при работе с CORS как таковым:

Показатель:

  • Простая версия CORS
  • Предварительная проверка версии CORS
  • Запросы с учетными данными

Простая версия CORS

  1. You can use GET, HEAD or POST:
    • In any of the method cases, you CANNOT set custom headers.
    • Вы всегда можете ограничить доступ к домену на стороне сервера через заголовок Access-Control-Allow-Origin.
  2. And if POST has request data:
    • Content-Type MUST BE either of the followings:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • текст/html

Эта ПРОСТАЯ версия явно НЕ ваш случай...

Предварительная проверка версии CORS

  1. You can use GET, HEAD or POST:
    • In any of the method cases, you CAN set custom headers.
    • Вы всегда можете ограничить доступ к домену на стороне сервера через заголовок Access-Control-Allow-Origin.
  2. And if POST has request data:
    • Content-Type MAY BE of the followings:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • текст/html
    • Content-Type CAN ALSO BE of other types:
      • application/json
      • приложение/xml
      • текст/xml
      • и т. д.

Эта ПРЕДВАРИТЕЛЬНАЯ версия явно ИМЕЕТ ваш случай...

Запросы с учетными данными

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

Запросы с учетными данными — это, безусловно, и ваш случай...

person mxcgi    schedule 11.08.2014

В соответствии с Запросом между источниками и спецификациями предварительной проверки учетные данные, то есть файл cookie сеанса, не отправляется в предварительном запросе, поэтому решение состоит в том, чтобы отключить безопасность для запросов OPTIONS на стороне вашего сервера REST и разрешить запросы без файла cookie сеанса только для запросов OPTIONS.

Конечно, будьте осторожны, чтобы не отключить безопасность для запросов POST и GET.

person Amir Jamak    schedule 14.03.2014

Согласно https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Чтобы разрешить использование файлов cookie в POST, необходимо настроить удаленный доступ с помощью Access-Control-Allow-Credentials: true.

Если вы используете причал, вам необходимо настроить

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

И цитата из статьи MDN,

Важное примечание: при ответе на запрос учетных данных сервер должен указывать домен и не может использовать подстановочные знаки. Приведенный выше пример потерпит неудачу, если заголовок будет иметь подстановочный знак: Access-Control-Allow-Origin: *. Поскольку в Access-Control-Allow-Origin явно упоминается http://foo.example, содержание, учитывающее учетные данные, возвращается в вызывающий веб-контент.

person Shen liang    schedule 19.04.2014