即使服务器返回适当的响应标头,Firefox 也不允许 CORS 请求

Posted

技术标签:

【中文标题】即使服务器返回适当的响应标头,Firefox 也不允许 CORS 请求【英文标题】:Firefox Does not allow CORS request even when the server returns the appropriate response header 【发布时间】:2015-01-16 02:07:47 【问题描述】:

我的应用使用 CORS 发出 ajax 请求,该请求在 Chrome 中有效,但在 Firefox 中无效。我关注了MDN CORS instructions,但它不起作用。

这是我的代码的省略视图:

var href = ...
var request = new XMLHttpRequest();
request.open('GET', href, true);
request.setRequestHeader("Accept", "application/json");
request.onload = ...
request.onerror = ...
try 
  request.send();
 catch (e) 
  console.log(e.message);

这会导致 NS_ERROR_DOM_BAD_URI 异常,消息“访问受限 URI 被拒绝”和代码 = 1012。

服务器以 Access-Control-Allow-Origin: http://localhost:13000 响应,我在 Chrome 中发出请求时验证了这一点。我想查看 FF 中的响应标头,但 Web 开发人员控制台仅向我显示了对 javascript 文件的 GET 请求,而且我看不到检查 ajax 请求和响应的标头的方法。验证飞行前请求也很好,这应该是设置自定义标头的结果,但我看不到如何使用调试器访问它。

【问题讨论】:

【参考方案1】:

我终于找到了一个解决方案,这似乎表明Firefox中的一个错误。

虽然我的示例代码中没有显示,但服务器需要 HTTP BASIC 身份验证,提供如下:

request.open('GET', href, true, username, password);
request.withCrednetials = true;

这符合MDN specification for XMLHttpRequest。

虽然这适用于 Chrome,但对于 Firefox,它会导致 ajax 请求不被发送(至少它不会出现在 Firebug 的控制台或网络窗格中)并且 send() 方法会抛出一个异常,声称正在向非法域发出请求。

以下解决方案适用于 FF 和 Chrome:

var href = ...
var username = ...
var password = ...
var request = new XMLHttpRequest();
request.open('GET', href, true); //do not include credentials, or FF will fail to send the request
request.setRequestHeader("Accept", "application/json");
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
request.onload = ...
request.onerror = ...
try 
  request.send();
 catch (e) 
  console.log(e.message);

请注意,如果将用户名和密码作为参数提供给 open(),Firefox 将无法发送请求并引发非法域异常,即使在 Authorization 标头中设置了凭据。

【讨论】:

以上是关于即使服务器返回适当的响应标头,Firefox 也不允许 CORS 请求的主要内容,如果未能解决你的问题,请参考以下文章

NSURLConnection 即使在重置授权标头后也会返回缓存的响应

Firefox 避免缓存响应?

即使返回的内容具有标头 Content-Type:text/html; Chrome 开发工具也无法显示响应字符集=UTF-8

即使在设置 CORS 标头和服务器响应之后,Angular 和 laravel 的 CORS 问题[重复]

响应标头中的 Azure 无服务器功能启用 CORS

即使响应正常,邮递员仍显示“无法得到任何响应”