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

max*_*tty 59 javascript ajax cors

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

第三方网站在其网页上包含以下代码段:

<script 
async="true"
id="web-dev-widget"
data-public-key="pUbl1c_ap1k3y"
src="http://web.dev/widget.js">
</script>
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

请注意,Access-Control-Allow-Origin设置为Origin而不是使用通配符,因为我发送了凭证请求(withCredentials).

现在一切都是为了进行异步跨域身份验证请求,它在OS X 10.8.2上的Chrome 25中运行良好.在Dev Tools中,我可以在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);
Run Code Online (Sandbox Code Playgroud)

这导致401 UnauthorizedOPTIONS请求的响应导致Google搜索,例如"为什么这在Chrome中起作用而不在Firefox中?" 就在那时我才知道自己遇到了麻烦.

为什么没有它在Chrome和Firefox的不是工作?如何获得OPTIONS发送和响应一致的请求?

max*_*tty 121

为什么没有它在Chrome和Firefox的不是工作?

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

Firefox有一个相关的错误归档,其中包含指向W3公共webapps邮件列表的链接,要求更改CORS规范以允许OPTIONS在IIS用户的帮助下在请求上发送身份验证标头.基本上,他们正在等待那些服务器被淘汰.

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

只需让服务器(本例中的API)响应OPTIONS请求而无需身份验证.

Kinvey在扩展这方面做得很好,同时也链接到Twitter API问题,在提交任何浏览器问题前几周,有趣地概述了这个确切场景的第22个问题.

  • 是否存在未对OPTION请求进行身份验证的安全风险? (21认同)
  • 对于那些在这里结束的人:值得使用`curl -X OPTIONS http:// yourdomain.example.com`来查看服务器响应OPTIONS请求的内容.还要确保您完全擦除浏览器缓存,Firefox会积极地缓存这些响应,因此即使您更改了服务器配置,它仍会报告相同的错误. (11认同)
  • 是否应该对OPTIONS请求始终提供相同的响应,还是应取决于请求的资源?如果取决于资源,则攻击者可以使用OPTIONS请求来发现该资源支持的服务器内容/ URL和功能。另请参阅以下问题:http://stackoverflow.com/questions/20805058/options-request-authentication (2认同)

小智 6

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

<LimitExcept OPTIONS>
    AuthType Basic
    AuthName <AUTH_NAME>
    Require valid-user
    AuthUserFile <FILE_PATH>
</LimitExcept>
Run Code Online (Sandbox Code Playgroud)