我正在使用凭据和预检请求实现 CORS,我有点困惑为什么预检请求在 Firefox 30 中始终失败,但在 Safari (7.0.2) 和 Chrome 35 中有效。我认为这个问题与“为什么经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?”因为我没有收到 401,而是来自浏览器客户端的 CORS 特定消息:
“跨源请求被阻止:同源策略不允许读取 http://myurl.dev.com 上的远程资源。可以通过将资源移至同一域或启用 CORS 来解决此问题。”
在不显示源代码的情况下,这就是我正在做的事情:
在服务器上:
选项响应的标题:
POST 响应的标题:
在浏览器客户端中:
jQuery.ajax({
url: requestUrl,
type: 'POST',
data: getData(),
xhrFields: {
withCredentials: true
}
});
根据规范,这将触发 OPTIONS 预检请求,该请求需要在其响应中包含 CORS 标头。 我已多次阅读 W3C 规范,但我无法确定在预检响应中我做错了什么(如果有的话)。
问题:“为什么此 CORS 请求仅在 Firefox 中失败?”
答案: 虽然与 OP 的具体情况无关,但它可能会帮助您了解 Firefox 默认情况下不信任 Windows 证书存储中的 CA(证书颁发机构),这可能会导致 Firefox 中的 CORS 请求失败(正如 Svish 在问题评论中提到的那样)。
允许 Firefox 信任 Windows 证书存储中的 CA:
about:config
security.enterprise_roots.enabled
作为名称
将值设置为 true
请注意,Firefox 是唯一兼容的浏览器。如果按照
https://fetch.spec.whatwg.org/#cors-preflight-fetch解析
Access-Control-Allow-Methods
失败,则需要返回网络错误。根据标头值的 ABNF,它绝对是一个逗号分隔值。
自 Firefox 87(2021 年 3 月发布)起,可以在 about:config(即 Firefox 配置编辑器)中设置以下首选项:
network.cors_preflight.allow_client_cert: true
来自 Firefox for Enterprise 87 - 发行说明:
使用 TLS 客户端证书的公司可以翻转
首选项,以获得与 Google Chrome 兼容的 CORS 协议处理。特别是,与 Fetch 标准相反,这将传输 TLS 客户端证书以及 CORS 预检。请参阅 bug 1511151 了解更多信息。network.cors_preflight.allow_client_cert
在 Firefox 中禁用 HTTPS-Only 模式解决了我的问题。 我试图使用 HTTP 从 http://localhost 访问远程资源。
我注意到,当您发送设置了 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/
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
托管本地服务器是安全的方式,不需要更改安全设置。 如果您使用 Visual Studio Code,以下扩展会很有帮助: 实时预览 - Visual Studio Marketplace
因为预览和调试功能等等都有说明。