为什么这个CORS请求仅在Firefox中失败?

时间:2014-07-01 15:58:32

标签: firefox cors fetch-api

我正在使用凭据和预检请求实施CORS,我有点迷惑为什么预检请求在Firefox 30中始终失败但在Safari(7.0.2)和Chrome 35中有效。我认为这个问题与" Why does the preflight OPTIONS request of an authenticated CORS request work in Chrome but not Firefox?"不同因为我没有收到401,而是来自浏览器客户端的特定于CORS的消息:

  

"阻止跨源请求:同源策略禁止在http://myurl.dev.com读取远程资源。这可以通过将资源移动到同一域或启用CORS来解决。"

没有显示源代码,这就是我正在做的事情:

在服务器上

OPTIONS响应的标题:

  • 访问控制 - 允许 - 来源:[[来自请求的来源]]
  • 访问控制 - 允许 - 方法:" POST GET OPTIONS"
  • Access-Control-Allow-Headers:" X-Requested-With"
  • Access-Control-Allow-Credentials:" true"

POST响应的标题:

  • 访问控制 - 允许 - 来源:[[来自请求的来源]]
  • Access-Control-Allow-Credentials:" true"

在浏览器客户端中:

jQuery.ajax({
  url: requestUrl,
  type: 'POST',
  data: getData(),
  xhrFields: {
    withCredentials: true
  }
});

根据规范,这将触发OPTIONS预检请求,该请求需要在其响应中包含CORS头。我已多次阅读W3C规范,但我无法确定我在该预检响应中做错了什么。

2 个答案:

答案 0 :(得分:1)

问题:“为什么此 CORS 请求仅在 Firefox 中失败?”


答案: 虽然与 OP 的具体情况无关,但它可能有助于您了解 Firefox 默认不信任 Windows 证书存储中的 CA(证书颁发机构) ,这可能会导致 Firefox 中的 CORS 请求失败(正如 Svish 在问题评论中所暗示的那样)。


允许 Firefox 信任 Windows 证书存储中的 CA:

  • 在 Firefox 中,在地址栏中输入 about:config
  • 如果出现提示,请接受任何警告
  • 右键单击以创建一个新的布尔值,然后输入 security.enterprise_roots.enabled 作为名称 将值设置为 true
  • 然后重新测试失败的请求

答案来源:https://support.umbrella.com/hc/en-us/articles/115000669728-Configuring-Firefox-to-use-the-Windows-Certificate-Store

答案 1 :(得分:0)

我注意到当您发送带有Cookie设置的CORS(跨源资源共享)请求时,Firefox不会发送所需的响应标头。

解决方案:

以下解决方案仅为OPTIONS请求添加标头,并仅接受来自example.com的请求。您可以更改其他请求方法和预期主机的实现。

JS CODE

var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;

xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == XMLHttpRequest.DONE) {
        if (xmlhttp.status == 200) {
            success_callback(xmlhttp.responseText);
        } else {
            error_callback(xmlhttp.statusText);
        }
    }
};
xmlhttp.open("DELETE", url);
xmlhttp.send(null);

当您发送DELETE请求时,浏览器会发送OPTIONS的转发前请求,该请求需要响应标头中的 Access-Control-Allow-Methods 。根据此标头值,发送实际的DELETE请求。在Firefox中,当您发送DELETE请求时,飞行前请求的响应标头没有预期的标头,因此无法发送实际的DELETE请求。

要解决此问题,请使用以下NGINX服务器配置。

NGINX代码

#handle CORS requests by adding required headers
if ($http_origin ~* .example.com) {
    set $cors "CORS-${request_method}";
}

if ($cors = "CORS-OPTIONS") {
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'Content-Type';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
    add_header 'Access-Control-Allow-Origin' $http_origin;
}

关于CORS的好读:https://www.html5rocks.com/en/tutorials/cors/