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

问题描述 投票:0回答:7

我正在使用凭据和预检请求实现 CORS,我有点困惑为什么预检请求在 Firefox 30 中始终失败,但在 Safari (7.0.2) 和 Chrome 35 中有效。我认为这个问题与“为什么经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?”因为我没有收到 401,而是来自浏览器客户端的 CORS 特定消息:

“跨源请求被阻止:同源策略不允许读取 http://myurl.dev.com 上的远程资源。可以通过将资源移至同一域或启用 CORS 来解决此问题。”

在不显示源代码的情况下,这就是我正在做的事情:

在服务器上

选项响应的标题:

  • Access-Control-Allow-Origin:[[从此处复制请求的来源]]
  • 访问控制允许方法:“POST GET 选项”
  • 访问控制允许标头:“X-Requested-With”
  • 访问控制允许凭据:“true”

POST 响应的标题:

  • Access-Control-Allow-Origin:[[从此处复制请求的来源]]
  • 访问控制允许凭据:“true”

在浏览器客户端中:

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

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

firefox cors fetch-api
7个回答
91
投票

问题:“为什么此 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


22
投票

请注意,Firefox 是唯一兼容的浏览器。如果按照

https://fetch.spec.whatwg.org/#cors-preflight-fetch
解析 Access-Control-Allow-Methods 失败,则需要返回网络错误。根据标头值的 ABNF,它绝对是一个逗号分隔值。


7
投票

Firefox 87(2021 年 3 月发布)起,可以在 about:config(即 Firefox 配置编辑器)中设置以下首选项:

network.cors_preflight.allow_client_cert: true

来自 Firefox for Enterprise 87 - 发行说明

使用 TLS 客户端证书的公司可以翻转

network.cors_preflight.allow_client_cert
首选项,以获得与 Google Chrome 兼容的 CORS 协议处理。特别是,与 Fetch 标准相反,这将传输 TLS 客户端证书以及 CORS 预检。请参阅 bug 1511151 了解更多信息。

参考资料:


3
投票

在 Firefox 中禁用 HTTPS-Only 模式解决了我的问题。 我试图使用 HTTP 从 http://localhost 访问远程资源。


0
投票

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

解决方案:

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

JS代码

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/


0
投票

Ubuntu 用户 有 2 个步骤来修复它:

1- 这个解决方案

2- 在终端中输入此命令:

sudo cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
    "policies": {
        "Certificates": {
            "Install": [
                "/usr/local/share/ca-certificates/aspnet/https.crt"
            ]
        }
    }
}
EOF

来源: https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-7.0&tabs=visual-studio%2Clinux-ubuntu


0
投票

托管本地服务器是安全的方式,不需要更改安全设置。 如果您使用 Visual Studio Code,以下扩展会很有帮助: 实时预览 - Visual Studio Marketplace

因为预览和调试功能等等都有说明。

© www.soinside.com 2019 - 2024. All rights reserved.