$ 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
действительно установлен (я не видел его в заголовке запроса)?
Любая помощь приветствуется!
Ответы
Ответ 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