为什么经过身份validation的CORS请求的预检选项请求在Chrome中运行,而不是在Firefox中运行?
我正在编写一个JavaScript客户端以包含在第三方网站上(请考虑Facebook Likebutton)。 它需要从需要基本HTTPauthentication的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已被configuration为使用适当的头文件进行响应:
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)?://(.+?\.[az]{3})$" AccessControlAllowOrigin=$0 Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
请注意, Access-Control-Allow-Origin
被设置为Origin
而不是使用通配符,因为我正在发送凭证请求( withCredentials
)。
现在一切都已经到位,可以实现跨域身份validation的asynchronous请求了,而且在OS X 10.8.2的Chrome 25上也可以运行。 在Dev Tools中,我可以在GET
请求之前看到OPTIONS
请求的networking请求,并且响应按预期返回。
在Firefox 19中testing时,Firebug中没有networking请求出现在API中,并且在控制台中logging了此错误: NS_ERROR_DOM_BAD_URI: Access to restricted URI denied
经过大量的挖掘,我发现Gecko不允许根据评论直接在一个跨站点的URI中input用户名和密码 。 我认为这是从使用可选的用户和密码参数open()
所以我尝试了其他方法进行身份validation的请求,这是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);
这会导致401 Unauthorized
响应OPTIONS
请求,导致谷歌search,如“为什么这个工作在Chrome而不是Firefox? 那时我知道我有麻烦了。
为什么它在Chrome而不是Firefox中工作? 我如何获得OPTIONS
请求一致发送和响应?
为什么它在Chrome而不是Firefox中工作?
CORS预检请求的W3规范明确指出,应排除用户证书。 Chrome和WebKit中存在一个错误,其中OPTIONS
请求返回状态401仍然发送后续请求。
Firefox有一个相关的错误提交,以W3公共webapps邮件列表的链接结尾,要求将CORS规范更改为允许在IIS用户的利益下在OPTIONS
请求上发送身份validation头。 基本上,他们正在等待这些服务器被淘汰。
我怎样才能得到OPTIONS
请求一致发送和响应?
只需要服务器(本例中的API)就可以响应OPTIONS
请求而不需要validation。
Kinvey在这方面做得很好,同时也连接到了一个Twitter API的问题,这个问题在任何一个浏览器问题提交之前几个星期都有趣地概述了这个确切的场景的catch-22问题。