【问题标题】:$http response Set-Cookie not accessible$http 响应 Set-Cookie 不可访问
【发布时间】:2014-02-26 13:22:27
【问题描述】:

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

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

我试过阅读

Set-Cookie in HTTP header is ignored with AngularJS

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

但不幸的是,我已经尝试了那里的所有解决方案,但似乎都不起作用。

请求已发送

收到回复

我正在使用 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 开发者工具的响应头中,但打印输出只是

只有Set-Cookie 在响应头没有被打印出来。我想知道为什么会发生这种情况?有没有办法让我确保确实设置了withCredentials=true(我没有在请求标头中看到它)?

感谢任何帮助!

【问题讨论】:

  • 你在服务器端试过Access-Control-Expose-Headers吗?这解决了我遇到的标题问题。 developer.mozilla.org/en-US/docs/HTTP/…
  • @slamborne 我刚刚尝试设置Access-Control-Expose-Headers:Set-Cookie,但没有奏效。我的猜测是值是我想公开的标题?

标签: javascript angularjs http cookies http-headers


【解决方案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 + 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只在摘要后与浏览器的cookies同步。

【讨论】:

  • 将 cookie 与浏览器同步的超时让我很开心。
  • @Ilan Frumer,这个解决方案在 Angular 的 1.3.14 版本中被破坏了。有什么想法吗?
  • 我可以得到这些值,这要归功于 $cookies。另外,有没有办法获取这些 cookie 的到期日期?
【解决方案2】:

在 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获取。

希望它会有所帮助。

【讨论】:

  • 这在 1.3.15 上不起作用,即使在 $http 请求中使用 withCredentials: true + 在 $httpProvider 中,即使在 $timeout 之后... $cookies 始终为空。跨度>
  • 我解决了我的具体问题,而不是一般:stackoverflow.com/questions/30011315/…
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    您是否真的需要在 Angular 中读取 cookie,或者如果它被设置并在浏览器的进一步请求中传递回就足够了?虽然我无法让前者工作,但我能够通过非常相似的配置让后者快速工作。 (特别是,我无法按照@Ilan 的建议使用$cookies。它什么也没返回。)

    首先,在 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。)

    【讨论】:

      【解决方案5】:

      设置'access-control-expose-headers', '*'

      Node API 示例

      router.get('/your-route', async (req, res) => {
          //..
          res.setHeader('access-control-expose-headers', '*' );
          //..
      })
      

      【讨论】:

        猜你喜欢
        • 2015-08-15
        • 2013-10-23
        • 2016-12-01
        • 2017-07-22
        • 2014-02-26
        • 2018-11-14
        • 2011-06-07
        • 2020-02-11
        • 2018-03-16
        相关资源
        最近更新 更多