【问题标题】:Angularjs $http does not seem to understand "Set-Cookie" in the responseAngularjs $http 似乎不理解响应中的“Set-Cookie”
【发布时间】:2013-10-23 09:08:14
【问题描述】:

我有一个带有 Passport 模块的 nodejs express REST api 用于身份验证。 登录方法 (GET) 在标头中返回一个 cookie。当我从 Chrome 调用它时,它工作正常,我的 cookie 是在我的浏览器中设置的。

但是如果我通过 $http 从 Angularjs 调用它,cookie 没有设置。

Set-Cookie:connect.sid=s%3Ad7cZf3DSnz-IbLA_eNjQr-YR.R%2FytSJyd9cEhX%2BTBkmAQ6WFcEHAuPJjdXk3oq3YyFfI; Path=/; HttpOnly

如上所示,Set-Cookie 存在于 http 服务响应的标头中。

也许 HttpOnly 可能是这个问题的根源?如果是,我该如何更改?这是我的快速配置:

app.configure(function () {
    app.use(allowCrossDomain);
    app.use(express.bodyParser());
    app.use(express.cookieParser())
    app.use(express.session({ secret: 'this is a secret' }));
    app.use(flash());
    //passport init
    app.use(passport.initialize());
    app.use(passport.session());
    app.set('port', process.env.PORT || 8080);
});

感谢您的帮助

【问题讨论】:

  • 您能否提供调用 $http 进行登录的 Angular 方法。暂时不知道怎么回事

标签: node.js angularjs express


【解决方案1】:

确保将您的 $http 请求配置为使用凭据。 来自 XHR 文档:

https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

XMLHttpRequest 和 访问控制是发出“有凭证的”请求的能力,这些请求是 了解 HTTP Cookie 和 HTTP 身份验证信息。经过 默认情况下,在跨站点 XMLHttpRequest 调用中,浏览器不会 发送凭据。必须在 XMLHttpRequest 上设置一个特定的标志 对象被调用时。

你可以使用options对象来设置凭证的使用,见

http://docs.angularjs.org/api/ng.$http

例子:

$http({withCredentials: true, ...}).get(...)

【讨论】:

  • 但是 AngularJS 仍然无法理解响应中的set-cookie
  • 我花了一天多的时间才意识到withCredentials = true 不仅告诉浏览器在请求时附加 cookie,而且还告诉它在响应时保存新的 cookie。这与 fetch 函数的 ajax 选项相同,其中必须应用 credentials: 'include' 以使浏览器根据请求和响应发送和设置 cookie。 IE。发送login ajax 请求到专用api 时,虽然不需要cookie,但必须设置withCredentials=true 否则接收到的sessionid cookie 将可用但浏览器不会保存它。
【解决方案2】:

您如何检查 cookie 是否存在?

$http 只是浏览器 XHR 的包装,就像 jQuery 的 $.ajax 和朋友一样。这意味着您的浏览器将正常处理 cookie。

我的猜测是 cookie 正在设置,但您正试图通过 document.cookie 读取它。 HttpOnly 阻止脚本访问 cookie。 这是一件好事。

HttpOnly 有助于缓解 XSS 攻击。它使恶意脚本无法窃取用户的会话令牌(以及他们的登录)。 不要关闭HttpOnly

无论如何,您应该不需要 cookie。由于$http 只是 XHR 的一个包装器,因此浏览器会在您下次发出请求时自动发送 cookie。您可以通过查看开发者工具的网络面板中的请求来验证这一点。

【讨论】:

  • 我会编辑帖子以解决将 withCredentials 设置为 true 的特定要求。没有它,它不会发送 cookie 以及 Access-Control-Allow-Credentials 标头。关于 HttpOnly 的 cmets,这是一个非常好的点 +1,可以确保一切都是安全的。
【解决方案3】:

我通过在角度 $http 请求中设置 {withCredential : true} 并通过设置解决了这个问题:

res.header("Access-Control-Allow-Credentials", true);

在我的快速服务器配置中。通过这样做,我的 cookie 会很好地出现在我的浏览器 cookie 列表中。

【讨论】:

    【解决方案4】:

    以下解决方案对我有用

    Angular 中,我使用了以下代码 sn-p withCredentials: true 我的请求。

    this._http.post(this._apiUrl + 'api/' + url, data, { withCredentials: true })
                .subscribe(data => { resolve(data) }, error => { this.showServerError(error)})
    

    在 Node 中,在获得解决方案之前,我只是使用

    初始化 CORS
    app.use(cors());
    

    但是,现在我已经实现了下面的代码sn-p

    app.use(cors({origin: [
       "http://localhost:5000"
     ], credentials: true}))
    

    http://localhost:5000 是我的 Angular 应用程序端点。你 可以从 config 或 .env 文件中动态设置这个 URL。

    希望上述解决方案能解决您的问题。

    【讨论】:

      【解决方案5】:

      你可以通过配置express.session来改变它:

      app.use(express.session({
        secret : 'this is a secret',
        cookie : {
          httpOnly : false,
          maxAge   : XXX // see text
        }
      });
      

      但我认为 Angular 不太关心 cookie,它们由浏览器处理(我同意 @josh3736 的观点,即您应该将 httpOnly 保留为 true)。

      这可能与您的 cookie 是(浏览器)会话 cookie 有关。您可以通过为 cookie 显式设置 maxAge(以毫秒为单位)来尝试看看它是否效果更好。

      【讨论】:

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