CORS withCredentials XHR 预检未在 Firefox 中发布 Cookie

Posted

技术标签:

【中文标题】CORS withCredentials XHR 预检未在 Firefox 中发布 Cookie【英文标题】:CORS withCredentials XHR preflight not posting Cookies in Firefox 【发布时间】:2012-04-25 09:14:03 【问题描述】:

我正在尝试发布带有凭据的 CORS XHR 帖子。它在 Chrome 中运行良好,但在 Firefox 中则不行。 cookie 不存在于飞行前请求标头中,因此我看到 302。这在 Chrome 中非常有效,因为 cookie 位于飞行前请求标头中,并且随后的 POST 会通过。

为什么这在 FF 中不起作用?我错过了什么?

// assume url, boundEventHandler and uploadData are defined, as this definitely works in Chrome
var xhr = new XMLHttpRequest(); 
xhr.open("POST", url, true); 
xhr.addEventListener ("readystatechange", boundEventHandler, false); 
xhr.withCredentials = true;  // FWIW, I've also tried the string 'true'
xhr.send(uploadData);

有什么想法吗?我看到一些帖子说我可以在服务器端代理请求,但我更愿意根据 CORS 规范来让它工作。

谢谢!

【问题讨论】:

你用的是什么版本的FF,最新的? 【参考方案1】:

根据 https://www.w3.org/TR/cors/#resource-preflight-requests 的规范,预检请求从不包含 cookie。具体来说,规范说:

排除用户凭据。

链接到https://www.w3.org/TR/cors/#user-credentials,上面写着:

在本规范中,术语用户凭据是指 cookie、HTTP 身份验证和客户端 SSL (...)。

也就是说,您上面引用的代码 sn-p 根本不应该涉及预检:没有上传事件侦听器,方法与简单方法一样,并且没有设置作者标头。因此,如果您真的看到预检请求,第一个问题是为什么会发生这种情况。您在 Firefox 中是否有任何扩展可能会修改您的 XMLHttpRequest 对象?

【讨论】:

好点...我在代码 sn-p 中省略了上传事件侦听器。不幸的是,规范不允许这样做。似乎如果有人想包含 cookie,他们应该被允许。 预检请求的重点是保护服务器免受网页的影响,让服务器知道有人想做某种奇怪的请求,并允许服务器在以下情况下明确地将此类事情列入白名单它知道如何正确处理它们......因为默认情况下许多服务器不知道如何正确处理它们。这意味着没有 cookie,因为这会打开针对毫无戒心的服务器的攻击媒介。允许 cookie 的唯一方法是如果 server 指示的 cookie 是允许的。但它会怎么做呢?对预检的响应是它是如何做到的。 有趣。我刚刚测试过,Chrome 根本没有为上传事件监听器做预检。这似乎......坏了 看起来 Chrome 的行为确实是 WebKit 中的一个安全漏洞,几天前已修复。见trac.webkit.org/changeset/113589 这真的很有帮助!我在应用程序引擎中对我的选项方法强制执行身份验证,这导致服务器返回同样的错误 302。删除 options 方法上的身份验证允许我的 XHR 现在正确响应。【参考方案2】:

现在 Chromium(2014 年 7 月 4 日)不会通过预检请求发送 cookie。 https://code.google.com/p/chromium/issues/detail?id=377541

【讨论】:

以上是关于CORS withCredentials XHR 预检未在 Firefox 中发布 Cookie的主要内容,如果未能解决你的问题,请参考以下文章

CORS withCredentials XHR 预检未在 Firefox 中发布 Cookie

CORS withCredentials - 支持有限?

Internet Explorer 10 忽略 XMLHttpRequest 'xhr.withCredentials = true'

使用 CORS 请求设置 Cookie

xhr.withCredentials发送跨域请求凭证

为 withCredentials 指定 CORS 标头:true