简体   繁体   English

$http 响应 Set-Cookie 不可访问

[英]$http response Set-Cookie not accessible

I'm currently writing an angularjs frontend to my backend, and I'm running into a somewhat common issue:我目前正在为我的后端编写一个 angularjs 前端,我遇到了一个常见的问题:

Server sends a cookie back in a response, but is completely ignored by angular.js (can't even print out the 'Set-Cookie' value).服务器在响应中发回 cookie,但被 angular.js 完全忽略(甚至无法打印出“Set-Cookie”值)。

I've tried reading我试过阅读

Set-Cookie in HTTP header is ignored with AngularJS<\/a> AngularJS 忽略 HTTP 标头中的 Set-Cookie<\/a>

Angularjs $http does not seem to understand "Set-Cookie" in the response<\/a> Angularjs $http 似乎不理解响应中的“Set-Cookie”<\/a>

but unfortunately I've tried all the solutions there and just doesn't seem to work.但不幸的是,我已经尝试了那里的所有解决方案,但似乎不起作用。

Request sent已发送请求

(由 Chrome 开发者工具捕获)

Response received收到回复

(由 Chrome 开发者工具捕获)

I'm using angular.js (v1.2.10), and this is what I used to make the request我正在使用 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;
                });

I looked inside $httpBackend source code: 我查看了$httpBackend源代码:

xhr.onreadystatechange = function() {

  // some code

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

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

      // some code

It uses XMLHttpRequest#getAllResponseHeaders to get the response headers. 它使用XMLHttpRequest#getAllResponseHeaders来获取响应头。

After a little search I found this question: xmlHttp.getResponseHeader + Not working for CORS 经过一番搜索,我发现了这个问题: xmlHttp.getResponseHeader +不适用于CORS

Which made me realize that XHR by it's specification, doesn't support SET-COOKIE , so it have nothing to do with angular.js in particular. 这让我意识到XHR的规格,不支持SET-COOKIE ,所以它与angular.js无关。

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

4.7.4 The getAllResponseHeaders() method 4.7.4 getAllResponseHeaders()方法

Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2 . 返回响应中的所有标头,但字段名称为Set-Cookie或Set-Cookie2的标头除外


Instead just use $cookies : 而只是使用$cookies

It's a different module so you must add it to your scripts 它是一个不同的模块,因此您必须将其添加到脚本中

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

And add it to the module dependencies: 并将其添加到模块依赖项:

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

Then just use it like so: 然后就像这样使用它:

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

  $scope.request = function(){

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

I use $timeout because $cookies only synchronize with browser's cookies after a digest. 我使用$timeout因为$cookies仅在摘要后与浏览器的cookie同步。

Do you actually need to read the cookie in Angular, or is it enough if it gets set and passed back on further requests by the browser? 你是否真的需要在Angular中读取cookie,或者它是否足够,如果它被设置并传回浏览器的进一步请求? While I wasn't able to get the former working, I was able to get the latter working pretty quickly with a very similar configuration. 虽然我无法让前者工作,但我能够以非常相似的配置让后者快速工作。 (In particular, I was not able to use $cookies as @Ilan recommended. It returned nothing.) (特别是,我无法使用$cookies作为@Ilan推荐。它什么也没有返回。)

First things first, on the Angular side configure the $httpProvider to send withCredentials by default: 首先,在Angular端配置$httpProvider默认发送withCredentials

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

That's all you have to do in Angular. 这就是你在Angular所要做的一切。 Note that, at this point, if you attempt to read $cookies it will still not be able to see the cookie, but it is saved and will be passed with future AJAX calls. 请注意,此时,如果您尝试读取$cookies它仍然无法看到cookie,但它会被保存并将在未来的AJAX调用中传递。

Then, on the server, you need to provide a specific domain (or a set of domains) allowed under CORS, along with the Access-Control-Allow-Credentials header. 然后,在服务器上,您需要提供CORS下允许的特定域(或一组域)以及Access-Control-Allow-Credentials标头。 My backend is Flask in Python with Flask-Restful and it looks like this: 我的后端是Flask in Python with 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)]

That's all it took. 这就是全部。 Now Angular (or, rather, the browser) sets the cookie and returns it with future requests completely transparently! 现在,Angular(或者更确切地说,浏览器)设置cookie并将其与未来的请求完全透明地返回!

(The same point is made here: https://stackoverflow.com/a/19384207/2397068 .) (同样的观点在这里: https//stackoverflow.com/a/19384207/2397068 。)

In Angular 1.3.14 it doesn't work anymore. 在Angular 1.3.14中它不再起作用。

I had the same problem. 我有同样的问题。 I am using $resource and declared withCredentials: true. 我正在使用$ resource并声明withCredentials:true。

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

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

or you can set the header "Access-Control-Allow-Credentials", "true". 或者您可以设置标题“Access-Control-Allow-Credentials”,“true”。

Now the cookie will be saved and you can get using $cookie. 现在cookie将被保存,您可以使用$ cookie。

Hope it will help. 希望它会有所帮助。

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

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

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

Example with Node API节点 API 示例

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM