【发布时间】:2013-03-21 23:19:26
【问题描述】:
我正在编写一个 JavaScript 客户端以包含在 3rd 方网站上(想想 Facebook 的 Like 按钮)。它需要从需要基本 HTTP 身份验证的 API 中检索信息。简化的设置如下所示:
第 3 方网站在其页面上包含此 sn-p:
<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 doesn't allow the username and password to be directly in a cross-site URI根据cmets。我假设这是使用可选的用户和密码参数到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 请求一致地发送和响应?
【问题讨论】:
-
我很想就如何使问题变得更好提供意见
标签: javascript ajax cors