我正在编写一个包含在第三方网站上的JavaScript客户端(想想Facebook赞按钮)。它需要从需要基本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中运行良好。在Dev Tools中,我可以在OPTIONS
请求之前看到GET
请求的网络请求,并且响应按预期返回。
在Firefox 19中进行测试时,Firebug中没有任何网络请求出现在API中,并且在控制台中记录了此错误:NS_ERROR_DOM_BAD_URI: Access to restricted URI denied
经过多次挖掘后,根据评论我发现了Gecko doesn't allow the username and password to be directly in a cross-site 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);
这导致对401 Unauthorized
请求的OPTIONS
响应,导致Google搜索,例如“为什么这在Chrome中运行而不是Firefox!?”就在那时,我知道自己遇到了麻烦。
为什么 它在Chrome中运行而不是Firefox?如何获得OPTIONS
请求发送和响应一致?
答案 0 :(得分:115)
为什么 它在Chrome中运行而不是Firefox?
W3 spec for CORS preflight requests明确指出应排除用户凭据。 Chrome和WebKit中存在一个错误,其中OPTIONS
请求返回状态401仍然发送后续请求。
Firefox有一个相关的错误归档,其中包含指向W3 public webapps mailing list的链接,要求更改CORS规范以允许在OPTIONS
请求上发送身份验证标头IIS用户的好处。基本上,他们正在等待那些服务器被淘汰。
如何才能获得OPTIONS
一致发送和回复的请求?
只需让服务器(本例中的API)响应OPTIONS
请求,而无需身份验证。
Kinvey在扩展这方面做得很好,同时在提交任何浏览器问题之前的几个星期,有趣地链接到an issue of the Twitter API概述了这个确切场景的第22个问题。
答案 1 :(得分:2)
这是一篇旧帖子,但也许这可以帮助人们完成CORS问题。要完成基本授权问题,您应该避免在服务器中对OPTIONS请求进行授权。这是一个Apache配置示例。只需在VirtualHost或Location中添加类似的内容即可。
<LimitExcept OPTIONS>
AuthType Basic
AuthName <AUTH_NAME>
Require valid-user
AuthUserFile <FILE_PATH>
</LimitExcept>
答案 2 :(得分:0)
对我来说很特别。我正在发送一个名为“ SESSIONHASH”的标头。 Chrome和Opera没问题,但是Firefox也希望在“ Access-Control-Allow-Headers”列表中使用此标头。否则,Firefox将抛出CORS错误。