Set-Cookie в HTTP-заголовке игнорируется с помощью AngularJS

Я работаю над приложением, основанным на AngularJS на стороне клиента и Java для моего API (Tomcat + Jersey for WS) на стороне сервера.

Некоторый путь моего API ограничен, если у пользователя нет сеанса, возвращается статус ответа 401. На стороне клиента перехватывается статус 401 http для перенаправления пользователя на страницу входа.

После аутентификации пользователя я создаю сеанс на стороне сервера

httpRequest.getSession(true);
и ответ, отправленный клиенту, имеет команду Set-cookie в заголовке:
Set-Cookie:JSESSIONID=XXXXXXXXXXXXXXXXXXXXX; Domain=localhost; Path=/api/; HttpOnly

Проблема в том, что cookie никогда не ставится на стороне клиента. Когда я проверяю файл cookie для домена localhost, он пуст, поэтому в следующих запросах нет этого файла cookie в заголовке и на стороне клиента, все еще не может получить доступ к ограниченному пути моего API.

Клиент и сервер находятся в одном домене, но у них нет одинакового пути и одного и того же номера порта:

Клиент: http://localhost:8000/app/index.html

Сервер: http://localhost:8080/api/restricted/

Дополнительная информация: CORS включен с обеих сторон:

"Access-Control-Allow-Methods", "GET, POST, OPTIONS"
"Access-Control-Allow-Origin", "*"
"Access-Control-Allow-Credentials", true

Любая идея создания Set-cookie работает правильно? Это проблема, связанная с AngularJS?

Ответ 1

Я нашел проблему в AngularJS, которая помогает мне двигаться вперед.

Кажется, что "Access-Control-Allow-Credentials" : true не было установлено на стороне клиента. Инструкция $httpProvider.defaults.withCredentials = true была проигнорирована.

Я заменяю вызов $resource простым $http-вызовом с {withCredentials: true} в параметре конфигурации.

Ответ 2

Мне удалось решить проблему, очень похожую на вашу. Моя игра! backend попытался установить сессию Cookie, которую я не смог поймать в Angular или сохранить через браузер.

На самом деле решение включало немного этого и немного того.

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

  • Вам нужно удалить HTTP-Only из заголовка Set-Cookie, иначе вы никогда не сможете получить cookie, сгенерированный вашим кодом Angular

    Эта настройка уже работает в Firefox, но не в Chrome

  • Чтобы заставить его работать и для Chrome, вам необходимо:

    a) отправить другой домен из локального хоста в файл cookie, используя домен, на котором размещены ваши WS. Вы даже можете использовать подстановочные знаки, такие как .domain.com вместо ws.domain.com

    b), тогда вам нужно будет позвонить в домен, указанный вами в файле cookie, иначе Chrome не сохранит ваш файл cookie

    [optional] Я бы удалил этот путь /api в пользу /


И это должно к трюку.
Надеюсь, что сможем помочь.

Ответ 3

В своем почтовом запросе на стороне клиента обязательно добавьте следующее:

Для запросов jQuery ajax:

$.ajax({
  url: "http://yoururlgoeshere",
  type: "post",
  data: "somedata",
  xhrFields: {
    withCredentials: true
  }
});

Ответ 4

Добавление HttpOnly означает, что браузер не должен позволять плагинам и JavaScript видеть cookie. Это недавнее соглашение о безопасном просмотре. Должен использоваться для J_SESSIONID, но, возможно, не здесь.

Ответ 5

Вам нужна работа как на стороне сервера, так и на стороне клиента.

Client

Установите $http config withCredentials в true одним из следующих способов:

  • По запросу

    var config = {withCredentials: true};
    $http.post(url, config);
    
  • Для всех запросов

    angular.module("your_module_name").config(['$httpProvider',
      function($httpProvider) {
        $httpProvider.interceptors.push(['$q',
          function($q) {
            return {
              request: function(config) {
                config.withCredentials = true;
                return config;
              }
            };
          }
        ]);
      }
    ]);
    

Сервер

Задайте заголовок ответа Access-Control-Allow-Credentials на true.

Ответ 6

Просто решил проблему вроде этого.

Я делал это и не работал...:

  $cookies.put('JSESSIONID', response.data);

Cookies сохраняются в браузере, но когда я отправил новый запрос, все куки были отправлены вне моего. (мой файл cookie - JSESSIONID)

тогда я смотрю в хромовом инспекторе, и я нашел это: Моя сессия - это JsessionID

ПРОБЛЕМА - ЭТО НЕ ПРАВИЛЬНОЕ ПУТЬ!!!

то я попробовал это, и мои файлы cookie были отправлены. ура!

$cookies.put('JSESSIONID', response.data, {'path':'/'});

Я не знаю, было ли это ваше дело, но это сработало для меня.

привет!