Подтвердить что ты не робот

Angularjs $http, похоже, не понимает "Set-Cookie" в ответе

У меня есть nodejs express REST api с модулем Passport для аутентификации. Метод входа (GET) возвращает куки файл в заголовке. Когда я вызываю его из Chrome, он отлично работает, мой файл cookie установлен в моем браузере.

Но если я назову его через $http из Angularjs, cookie не будет установлен.

Set-Cookie:connect.sid=s%3Ad7cZf3DSnz-IbLA_eNjQr-YR.R%2FytSJyd9cEhX%2BTBkmAQ6WFcEHAuPJjdXk3oq3YyFfI; Path=/; HttpOnly

Как вы можете видеть выше, Set-Cookie присутствует в заголовке ответа службы http.

Возможно, HttpOnly может быть источником этой проблемы? Если да, то как я могу его изменить? Вот моя экспресс-конфигурация:

app.configure(function () {
    app.use(allowCrossDomain);
    app.use(express.bodyParser());
    app.use(express.cookieParser())
    app.use(express.session({ secret: 'this is a secret' }));
    app.use(flash());
    //passport init
    app.use(passport.initialize());
    app.use(passport.session());
    app.set('port', process.env.PORT || 8080);
});

Спасибо за помощь

4b9b3361

Ответ 1

Обязательно настройте свой запрос $http для использования учетных данных. Из документации XHR:

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

Самая интересная возможность, предоставляемая как XMLHttpRequest, так и Контроль доступа - это возможность делать "учетные" запросы, которые cognizedant HTTP Cookies и HTTP-аутентификация. От по умолчанию, в межсайтовых вызовах XMLHttpRequest, браузеры не будут отправьте учетные данные. Определяющий флаг должен быть установлен на XMLHttpRequest объект, когда он вызывается.

Вы можете использовать объект options для установки использования учетных данных, см.

http://docs.angularjs.org/api/ng.$http

Пример:

$http({withCredentials: true, ...}).get(...)

Ответ 2

Как вы проверяете наличие файла cookie?

$http - это просто оболочка вокруг браузера XHR, как и jQuery $.ajax и друзей. Это означает, что ваш браузер будет обрабатывать файлы cookie как обычно.

Я предполагаю, что cookie настроен, но вы пытаетесь прочитать его через document.cookie. HttpOnly предотвращает доступ script к файлу cookie. Это хорошо.

HttpOnly помогает смягчить атаки XSS. Это делает невозможным вредоносное script красть токен сеанса пользователя (и, следовательно, их логин). Не отключайте HttpOnly.

В любом случае вам не нужен cookie. Поскольку $http - это всего лишь оболочка вокруг XHR, браузер автоматически отправит файл cookie при следующем запросе. Вы можете проверить это, просмотрев запросы на панели "Инструменты разработчика".

Ответ 3

Я решил проблему, установив {withCredential : true} в запрос angular $http и установив:

res.header("Access-Control-Allow-Credentials", true);

в конфигурации моего экспресс-сервера. Делая это, мой файл cookie появляется в списке файлов cookie браузера.

Ответ 4

Вы можете изменить его, настроив express.session:

app.use(express.session({
  secret : 'this is a secret',
  cookie : {
    httpOnly : false,
    maxAge   : XXX // see text
  }
});

Но я не думаю, что Angular много заботится о файлах cookie, которые обрабатываются браузером (и я согласен с @josh3736, что вы должны оставить httpOnly до true).

Возможно, это связано с вашими куки файлами cookie сеанса (браузером). Вы можете попробовать и посмотреть, работает ли это лучше, явно установив maxAge для файла cookie (в миллисекундах).

Ответ 5

Ниже решение сработало для меня

В Angular я использовал следующий фрагмент кода, используя withCredentials: true для моего запроса.

this._http.post(this._apiUrl + 'api/' + url, data, { withCredentials: true })
            .subscribe(data => { resolve(data) }, error => { this.showServerError(error)})

В Node, прежде чем я получил решение, я просто инициализировал CORS, используя

app.use(cors());

Но теперь я реализовал следующий фрагмент кода

app.use(cors({origin: [
   "http://localhost:5000"
 ], credentials: true}))

Где http://localhost: 5000 - моя конечная точка приложения Angular. Вы можете установить этот URL-адрес динамически из файла конфигурации или .env.

Надеюсь, что вышеуказанное решение будет работать для вашей проблемы.