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

$ HTTP-ответ Set-Cookie недоступен

В настоящее время я пишу интерфейс angularjs для своего бэкэнда, и я сталкиваюсь с несколько распространенной проблемой:

Сервер отправляет cookie обратно в ответ, но полностью игнорируется angular.js(не может даже распечатать значение "Set-Cookie" ).

Я пробовал читать

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

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

но, к сожалению, я пробовал все решения там и просто не работает.

Запрос отправлен

(as captured by Chrome Developer Tools)

Полученный ответ

(as captured by Chrome Developer Tools)

Я использую angular.js(v1.2.10), и это то, что я использовал для запроса

$http.post('/services/api/emailLogin',
           sanitizeCredentials(credentials), 
           {
              withCredentials: true
           }).success(function(data, status, header) {
                console.log(header('Server'));
                console.log(header('Set-Cookie'));
                console.log(header('Access-Control-Allow-Headers'));
                console.log(header('Access-Control-Allow-Methods'));
                console.log(header);
            }).then(
                function(response) {
                    console.log(response);
                    return response.data;
                });

withCredentials=true устанавливается на стороне клиента перед выполнением запроса.

Access-Control-Allow-Credentials=true устанавливается на стороне сервера перед возвратом ответа.

Вы можете четко видеть, что Set-Cookie находится в заголовках ответов от инструментов разработчика Chrome, но распечатка просто

(code printout)

Только заголовок Set-Cookie в заголовке ответа не распечатывается. Мне интересно, почему это происходит? Есть ли способ убедиться, что withCredentials=true действительно установлен (я не видел его в заголовке запроса)?

Любая помощь приветствуется!

4b9b3361

Ответ 1

Я заглянул в исходный код $httpBackend:

xhr.onreadystatechange = function() {

  // some code

  if (xhr && xhr.readyState == 4) {
    var responseHeaders = null,
        response = null;

    if(status !== ABORTED) {
      responseHeaders = xhr.getAllResponseHeaders();

      // some code

Он использует XMLHttpRequest#getAllResponseHeaders для получения заголовков ответов.

После небольшого поиска я нашел этот вопрос: xmlHttp.getResponseHeader + Не работает для CORS

Что заставило меня понять, что XHR по спецификации, не поддерживает SET-COOKIE, поэтому он не имеет ничего общего с angular.js в частности.

http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders%28%29-method

4.7.4 Метод getAllResponseHeaders()

Возвращает все заголовки ответа, , за исключением тех, чье имя поля Set-Cookie или Set-Cookie2.


Вместо этого просто используйте $cookies:

Это другой модуль, поэтому вы должны добавить его в свои скрипты

 <script src="angular.js"></script>
 <script src="angular-cookies.js"></script>

И добавьте его в зависимости от модуля:

 var app = angular.module('app',['ngCookies']);

Затем просто используйте его так:

app.controller('ctrl',  function($scope, $http , $cookies, $timeout){

  $scope.request = function(){

    $http.get('/api').then(function(response){
      $timeout(function(){
        console.log($cookies.session)
      });         
    })
  }
})

Я использую $timeout, потому что $cookies синхронизируется только с кукисами браузера после дайджеста.

Ответ 2

Вам действительно нужно прочитать файл cookie в Angular, или это достаточно, если оно будет установлено и передано на другие запросы браузером? В то время как я не смог получить прежнюю работу, мне удалось заставить последнего работать довольно быстро с очень похожей конфигурацией. (В частности, я не смог использовать $cookies, как рекомендовал @Ilan. Он ничего не возвращал.)

Прежде всего, на стороне Angular настройте $httpProvider для отправки withCredentials по умолчанию:

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.withCredentials = true;
}]);

Это все, что вам нужно сделать в Angular. Обратите внимание, что в этот момент, если вы попытаетесь прочитать $cookies, он все равно не сможет увидеть файл cookie, но он будет сохранен и будет передан с последующими вызовами AJAX.

Затем на сервере вам необходимо предоставить определенный домен (или набор доменов), разрешенный в CORS, вместе с заголовком Access-Control-Allow-Credentials. Мой бэкенд - это флажок в Python с Flask-Restful, и он выглядит так:

import Flask
from flask_restful import Api
app = Flask(__name__)
api = Api(app)
api.decorators = [cors.crossdomain(origin='http://localhost:8100', credentials=True)]

Это все, что нужно. Теперь Angular (или, скорее, браузер) устанавливает куки файл и возвращает его с будущими запросами полностью прозрачно!

(То же самое делается здесь: fooobar.com/questions/133713/....)

Ответ 3

В Angular 1.3.14 он больше не работает.

У меня была та же проблема. Я использую $resource и объявлен withCredentials: true.

 var fooRes = $resource('/address/exemple',
    {},
    {
        bar: {
            method: 'POST',
            withCredentials: true,
        }
    }
 );

 fooRes.bar({
     "stuff" : "lorem"
 }).$promise.then(function(){
     //callback
 })

или вы можете установить заголовок "Access-Control-Allow-Credentials", "true".

Теперь cookie будет сохранен, и вы можете использовать $cookie.

Надеюсь, это поможет.

Ответ 4

Вам нужно изменить файл .htaccess, чтобы разрешить чтение заголовков.

Header set Access-Control-Allow-Headers Content-Type