Angularjs $http 似乎不理解响应中的“Set-Cookie”

Posted

技术标签:

【中文标题】Angularjs $http 似乎不理解响应中的“Set-Cookie”【英文标题】:Angularjs $http does not seem to understand "Set-Cookie" in the response 【发布时间】: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 方法。暂时不知道怎么回事 【参考方案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(以毫秒为单位)来尝试看看它是否效果更好。

【讨论】:

以上是关于Angularjs $http 似乎不理解响应中的“Set-Cookie”的主要内容,如果未能解决你的问题,请参考以下文章

405 方法不允许使用 $http 服务 AngularJS

AngularJS $http 对象未显示响应中的所有标头

AngularJS 2/4 中 BehaviourSubject 中的 HTTP 响应缓存和下一步

AngularJS Post不工作

AngularJS 中的 JSONP 请求不像 jQuery 那样工作

预检响应中的 Access-Control-Allow-Headers 不允许授权