69

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

第三方网站在其页面上包含此代码段:

<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中。我假设这是使用可选的用户和密码参数,open()所以我尝试了另一种进行身份验证请求的方法,即对凭据进行 Base64 编码并发送授权标头:

// Base64 from http://www.webtoolkit.info/javascript-base64.html
auth = "Basic " + Base64.encode(user + ":" + pass);

...
// after open() and before send()
httpRequest.setRequestHeader('Authorization', auth);

这会导致对导致 Google 搜索401 Unauthorized的请求的响应,OPTIONS例如“为什么这在 Chrome 而不是 Firefox 中有效!?” 那时我知道我有麻烦了。

为什么适用于 Chrome 而不是 Firefox?如何获得OPTIONS一致发送和响应的请求?

4

3 回答 3

139

为什么适用于 Chrome 而不是 Firefox?

CORS 预检请求的W3 规范明确指出应排除用户凭据。ChromeWebKit中存在一个错误,即OPTIONS返回 401 状态的请求仍会发送后续请求。

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

如何获得OPTIONS一致发送和响应的请求?

只需让服务器(本例中为 API)响应OPTIONS请求而不需要身份验证。

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

于 2013-03-31T20:14:42.697 回答
7

这是一篇旧帖子,但也许这可以帮助人们完成 CORS 问题。要完成基本授权问题,您应该避免在服务器中对 OPTIONS 请求进行授权。这是一个 Apache 配置示例。只需在您的 VirtualHost 或 Location 中添加类似的内容。

<LimitExcept OPTIONS>
    AuthType Basic
    AuthName <AUTH_NAME>
    Require valid-user
    AuthUserFile <FILE_PATH>
</LimitExcept>
于 2018-05-18T17:28:54.823 回答
0

这对我来说很特别。我正在发送一个名为“SESSIONHASH”的标头。Chrome 和 Opera 没问题,但 Firefox 也希望在“Access-Control-Allow-Headers”列表中使用此标头。否则,Firefox 将抛出 CORS 错误。

于 2019-08-15T11:31:08.637 回答