$ http响应Set-Cookie无法访问

时间:2014-02-03 06:17:32

标签: javascript angularjs http cookies http-headers

我正在为我的后端写一个angularjs前端,我遇到了一个常见的问题:

服务器在响应中发回cookie,但angular.js完全忽略了cookie(甚至无法打印出'Set-Cookie'值)。

我试过读

Set-Cookie in HTTP header is ignored with AngularJS

Angularjs $http does not seem to understand "Set-Cookie" in the response

但不幸的是我在那里尝试了所有的解决方案,但似乎没有用。

发送请求

(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

您可以清楚地看到{+ 1}}位于Chrome开发者工具的响应标题中,但打印输出只是

(code printout)

响应标头中只有Set-Cookie未打印出来。我想知道为什么会这样?有没有办法让我确保Set-Cookie确实已设置(我在请求标头中没有看到它)?

感谢任何帮助!

4 个答案:

答案 0 :(得分:29)

我查看了$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 + Not working for 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仅在摘要后与浏览器的Cookie同步。

答案 1 :(得分:4)

你是否真的需要在Angular中读取cookie,或者如果它被设置并在浏览器的进一步请求中传回,它是否足够?虽然我无法让前者工作,但我能够以非常相似的配置让后者快速工作。 (特别是,我无法使用$cookies作为@Ilan推荐。它没有返回任何内容。)

首先,在Angular端配置$httpProvider默认发送withCredentials

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

这就是你在Angular所要做的一切。请注意,此时,如果您尝试阅读$cookies,它仍然无法看到cookie,但会保存并将在未来的AJAX调用中传递。

然后,在服务器上,您需要提供CORS下允许的特定域(或一组域)以及Access-Control-Allow-Credentials标头。我的后端是带有Flask-Restful的Python中的Flask,它看起来像这样:

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

这就是全部。现在,Angular(或者更确切地说,浏览器)设置cookie并将其与未来的请求完全透明地返回!

(同样的观点在这里:https://stackoverflow.com/a/19384207/2397068。)

答案 2 :(得分:0)

在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
 })

或者您可以设置标题&#34; Access-Control-Allow-Credentials&#34;,&#34; true&#34;。

现在,cookie将被保存,您可以使用$ cookie。

希望它会有所帮助。

答案 3 :(得分:0)

您需要修改.htaccess文件以允许读取标题。

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