为什么经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?

问题描述 投票:0回答:4

我正在编写一个 JavaScript 客户端,将其包含在第 3 方网站上(想想 Facebook Like 按钮)。它需要从需要基本 HTTP 身份验证的 API 检索信息。简化的设置如下所示:

第 3 方网站在其页面上包含此片段:

<script 
async="true"
id="web-dev-widget"
data-public-key="pUbl1c_ap1k3y"
src="http://web.dev/widget.js">
</script>

widget.js调用API:

var el = document.getElementById('web-dev-widget'),
    user = 'token',
    pass = el.getAttribute('data-public-key'),
    url = 'https://api.dev/',
    httpRequest = new XMLHttpRequest(),
    handler = function() {
      if (httpRequest.readyState === 4) {
        if (httpRequest.status === 200) {
          console.log(httpRequest.responseText);
        } else {
          console.log('There was a problem with the request.', httpRequest);
        }
      }
    };

httpRequest.open('GET', url, true, user, pass);
httpRequest.onreadystatechange = handler;
httpRequest.withCredentials = true;
httpRequest.send();

API 已配置为使用适当的标头进行响应:

Header set Access-Control-Allow-Credentials: true
Header set Access-Control-Allow-Methods: "GET, OPTIONS"
Header set Access-Control-Allow-Headers: "origin, authorization, accept"
SetEnvIf Origin "http(s)?://(.+?\.[a-z]{3})$" AccessControlAllowOrigin=$0
Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin

请注意,

Access-Control-Allow-Origin
设置为
Origin
而不是使用通配符,因为我正在发送凭据请求 (
withCredentials
)。

现在,发出异步跨域身份验证请求的一切都已就绪,并且在 OS X 10.8.2 上的 Chrome 25 中运行良好。在开发工具中,我可以在

OPTIONS
请求之前看到
GET
请求的网络请求,并且响应按预期返回。

在 Firefox 19 中测试时,Firebug 中不会出现对 API 的网络请求,控制台中会记录此错误:

NS_ERROR_DOM_BAD_URI: Access to restricted URI denied

经过大量挖掘,我发现根据评论,Gecko 不允许用户名和密码直接位于跨站点 URI 中。我认为这是使用可选的用户和密码参数来实现的,所以我尝试了另一种发出经过身份验证的请求的方法,即对凭据进行 Base64 编码并发送授权标头:


open()

这会导致对 
// Base64 from http://www.webtoolkit.info/javascript-base64.html auth = "Basic " + Base64.encode(user + ":" + pass); ... // after open() and before send() httpRequest.setRequestHeader('Authorization', auth);

请求的

401 Unauthorized
响应,从而导致 Google 搜索,例如“为什么这在 Chrome 中有效,而在 Firefox 中无效!?”那时我就知道我有麻烦了。

为什么

可以

它在 Chrome 中工作,而不是在 Firefox 中工作?如何才能一致地发送和响应 OPTIONS 请求?

    

javascript ajax cors
4个回答
148
投票
为什么

可以在 Chrome 中工作而不是在 Firefox 中工作? CORS 预检请求的

W3 规范

明确规定应排除用户凭据。 ChromeWebKit 中存在一个错误,其中 OPTIONS 请求返回 401 状态仍会发送后续请求。

Firefox

有一个相关的错误,以指向 W3 公共 webapps 邮件列表的链接结尾,要求更改 CORS 规范,以允许在 OPTIONS 请求上发送身份验证标头,这对 IIS 用户有利。基本上,他们正在等待这些服务器被淘汰。

如何才能一致地发送和响应

OPTIONS请求?


只需让服务器(本例中的 API)响应 

OPTIONS

请求,无需身份验证。

Kinvey

在这方面做得很好,同时还链接到 Twitter API 的一个问题,有趣的是,在提交任何浏览器问题之前几周,概述了这个确切场景的第 22 条军规问题。


10
投票

OPTIONS



0
投票


0
投票
仅供记录,原因在

另一个答案中得到了很好的解释,同时Firefox 87+提供了一个解决方法,正如最初解释的那样这里

Firefox 87

(2021 年 3 月发布)起,可以在 about:config(即 Firefox 配置编辑器)中设置以下首选项: <LimitExcept OPTIONS> AuthType Basic AuthName <AUTH_NAME> Require valid-user AuthUserFile <FILE_PATH> </LimitExcept>

来自 
Firefox for Enterprise 87 - 发行说明

使用 TLS 客户端证书的公司可以翻转

network.cors_preflight.allow_client_cert: true

 首选项,以获得与 Google Chrome 兼容的 CORS 协议处理。特别是,与 Fetch 标准相反,这将传输 TLS 客户端证书以及 CORS 预检。请参阅 
bug 1511151 了解更多信息。

参考资料:

    https://support.mozilla.org/en-US/kb/firefox-enterprise-87-release-notes
  • https://bugzilla.mozilla.org/show_bug.cgi?id=1511151
© www.soinside.com 2019 - 2024. All rights reserved.