同源请求会导致“Access-Control-Allow-Origin 不匹配”错误,尽管来源当然匹配。注意:具有带“沙盒”的 CSP 策略

Posted

技术标签:

【中文标题】同源请求会导致“Access-Control-Allow-Origin 不匹配”错误,尽管来源当然匹配。注意:具有带“沙盒”的 CSP 策略【英文标题】:Same-origin request causes “Access-Control-Allow-Origin doesn’t match” error, though origin of course matches. Note: has CSP policy w/ "sandbox" 【发布时间】:2020-09-29 00:20:33 【问题描述】:

当 CORS 及其网页的 URL 都使用 exact same URL 时,我的 Firefox 开发控制台中仍然会收到相同的错误消息。

浏览器控制台消息是:

Cross-Origin Request Blocked: \
  The Same Origin Policy disallows reading the remote resource \
  at https://egbert.net/fonts/fontawesome-webfont.woff2?v=4.7.0. \
  (Reason: CORS header ‘Access-Control-Allow-Origin’ does not \
  match ‘https://egbert.net’).

标头设置,lighttpd 服务器

Access-Control-Allow-Origin: https://egbert.net
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range
Content-Security-Policy: \
    default-src 'none'; \
    base-uri 'none'; \
    script-src 'strict-dynamic'; \
    object-src 'none'; \
    style-src 'self'; \
    img-src https://egbert.net/favicon.ico https://egbert.net/images/ https://egbert.net/blog/articles/*/images/*.png data:; \
    media-src https://egbert.net/media/ data:; \
    frame-src https://egbert.net/frames/; \
    frame-ancestors 'self'; \
    worker-src 'self'; \
    child-src https://egbert.net/frames/; \
    font-src https://egbert.net/fonts/; \
    connect-src 'self' https://egbert.net/; \
    form-action 'none'; \
    require-trusted-types-for; \
    trusted-types template; \
    sandbox; \
    report-uri https://ssoseo1.report-uri.com/r/d/csp/enforce; \
    report-to endpoint-1; \
    upgrade-insecure-requests; \
    block-all-mixed-content;
Feature-Policy: accelerometer 'none'; camera 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; notifications 'none'; payment 'none'; push 'none'; sync-xhr 'none'; speaker 'none'; usb 'none'; vibrate 'none';
Referrer-Policy: no-referrer

html 设置

  <link rel="stylesheet" href="https://egbert.net/css/m-dark.compiled.css">

CSS 路径

 */@font-face 
 font-family:'FontAwesome';
 src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');
 src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),
 url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),
 url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),
 url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),
 url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');
 font-weight:normal;
 font-style:normal

我已确保所有字体文件都可以通过同一浏览器在单独的选项卡中下载。

更奇怪的是,错误消息暗示“远程资源”。它们是完全相同的 URL。

没有加载插件,这是 Firefox v73.0.1 的安全模式。

更新 1

当我将 CSS 的 /@font-face 中的相对路径('../fonts')替换为绝对目录路径时,它并没有改变任何东西。

更新 2

当我将方案和域 (https://egbert.net/) 添加到 CSS 的 /@font-face 中时,它并没有改变任何东西,位于绝对目录路径前面,以获得完整的 URL 路径。

这与以下问题不同:

Why doesn’t Postman get a “No 'Access-Control-Allow-Origin' header is present on Font from origin has been blocked from loading by Cross-Origin Resource Sharing policy Firefox 'Cross-Origin Request Blocked' despite headers How to get a cross-origin resource sharing (CORS) post request working Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at Same origin Policy and CORS (Cross-origin resource sharing) Socket.IO: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource google maps - Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at Cross-Origin Request Blocked Microsoft Azure Function

【问题讨论】:

尝试将您的 Content-Security-Policy 响应标头更改为 sandbox allow-same-origin 而不仅仅是 sandbox — 否则,从您的 CSP 策略中完全删除 sandbox 指令。你添加它有什么特别的原因吗?你到底在用它来防止什么?需要添加allow-same-origin 的原因是,如果不添加sandbox,则浏览器需要将文档的来源设置为null。我认为这就是导致您的字体请求失败的原因:浏览器不会阻止请求,因为文档来源为空。 浏览器何时将原点设置为 null 的详细信息位于 ***.com/a/42242802/441757。 html.spec.whatwg.org/multipage/…,解释了他的案例中的具体情况:当sandbox被设置时,“内容被视为来自一个唯一的来源;禁用表单、脚本和各种可能令人讨厌的 API,阻止链接针对其他浏览上下文,并保护插件。 allow-same-origin 关键字导致内容被视为来自其真实来源,而不是强制其成为唯一来源” @sideshowbarker,就是这样!!!!问题解决了!在 HTTP 标头的 CSP 部分中将 'sandbox' 替换为 'sandbox allow-same-origin' 做到了这一点。哦,我的,哦,我的,真是一种解脱。 10 天的痛苦在……秒内解决了。至于我为什么要做这个安全事情,这是一个概念证明,一个人可以“超级”并让它工作,你做到了。非常感谢! 更新了 OP 以显示 HTTP-RESPONSE 标头的 CSP 部分。请为我的精彩接受发布答案,@sideshowbarker Mozilla 的一个错误报告,要求修复错误消息的措辞,以便其他人不会落入这个陷阱。 bugzilla.mozilla.org/show_bug.cgi?id=1644503 【参考方案1】:

在 CSP 策略中将 sandbox 替换为 sandbox allow-same-origin 将解决此问题。

说明:

问题描述的CORS问题最终是由浏览器将原始值设置为null引起的。因此,即使Access-Control-Allow-Origin 响应标头设置为通常预期的原始值——匹配浏览器地址栏中显示的 URL——它实际上并不匹配,因为浏览器已将源设置为null.

所以你最终会遇到一个悖论:文档似乎与它自己的来源不匹配。

https://***.com/a/42242802/441757 的答案概述了浏览器将原点设置为 null 的所有情况。问题中案例的具体原因来自https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox 的要求,如果设置了sandbox

内容被视为来自唯一来源,禁用表单、脚本和各种可能令人讨厌的 API,阻止链接针对其他浏览上下文,并保护插件。 allow-same-origin 关键字导致内容被视为来自其真实来源,而不是强制其成为唯一来源。

所以底线是:每当您指定 sandbox 时,在大多数情况下,您希望在指定时包含 allow-same-origin 关键字 — 以防止出现令人惊讶且难以解决的问题/副作用,例如正如问题中描述的CORS问题。

【讨论】:

似乎有更新...sandbox 属性适用于 iframe。 “仅”适用于 iframe?主/父 DOM 上下文/页面呢? html.spec.whatwg.org/multipage/… 基本上,这个HTTP规范是一种“TRI-STATE”逻辑机制。我们从“未知”开始,然后切换到“允许”或“不允许”。而“未知”默认为“不允许”?类似的东西? 指定sandbox 就像指定“禁止一切”或“拒绝一切”。因此,如果您指定了sandbox,但您想允许特定的事情,您需要使用allow-* 重新添加您想要允许的特定事情。

以上是关于同源请求会导致“Access-Control-Allow-Origin 不匹配”错误,尽管来源当然匹配。注意:具有带“沙盒”的 CSP 策略的主要内容,如果未能解决你的问题,请参考以下文章

浅析跨域请求

同源策略与跨域问题解决

前端跨域解决

分享 | 解决ajax跨域失败的那些个人经验

关于跨域,你应该知道的

一些面试高频题目