【问题标题】:With <script crossorigin='anonymous'>, why is a script "blocked by CORS policy"?使用 <script crossorigin='anonymous'>,为什么脚本“被 CORS 策略阻止”?
【发布时间】:2016-12-09 21:40:24
【问题描述】:

使用 Google Chrome 或 Firefox,如果我尝试加载以下 HTML:

<script crossorigin='anonymous' src='https://stackoverflow.com/foo.js'></script>

我收到这样的 CORS 错误:

CORS 策略已阻止从源“https://stackoverflow.com”访问“https://stackoverflow.com/foo.js”处的脚本:请求的资源上不存在“Access-Control-Allow-Origin”标头...

但是,没有crossorigin='anonymous' 属性的相同标记可以正常工作(当然会产生 404 错误,因为 foo.js 不存在)。

这令人惊讶,因为anonymous 只是supposed to prevent sending any credentials,而脚本标签are not supposed to require CORS。这是什么原因造成的,我该怎么办?

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    我有一段时间对此感到困惑。我现在是这样理解的:

    According to the W3Ccrossorigin 属性实际上有 三个 可能的值:anonymoususe-credentials,以及只能通过省略属性。 (另一方面,一个空字符串映射到 anonymous。)默认值会导致浏览器完全跳过 CORS,这是我所期望的正常行为。

    crossorigin 属性仅应在我们关心获取正在加载的脚本的错误信息时使用。由于访问此信息需要 CORS 检查,因此资源上必须存在 Access-Control-Allow-Origin 标头才能加载它。

    【讨论】:

    • 我会暂时不接受这个,以防有人想写一个更好的解释!
    • pdg137 你只需要让你的服务器在 JS 文件中返回这个响应头:Access-Control-Allow-Origin:*
    • 是的,这会有所帮助,但我通常不能或不想这样做。具体来说,在加载第三方脚本时。
    • 他们说“缺少默认值”,而不是“缺少默认值”。看到不同?您的回答令人困惑,这里没有“未命名的默认值”之类的东西。它只是匿名的、使用凭据或没有属性。跳过 CORS 的不是默认值,它只是缺少属性。
    • 我编辑了这篇文章以使其更清晰;如果有帮助,请告诉我。
    【解决方案2】:

    crossorigin 属性只有两个可能的值:anonymoususe-credentials。除了anonymous 之外的任何值,包括空值,都将被转换为anonymous

    所以这三个标签的意思是一样的:

    <script src="https://stackoverflow.com/foo.js" crossorigin="anonymous">
    <script src="https://stackoverflow.com/foo.js" crossorigin="">
    <script src="https://stackoverflow.com/foo.js" crossorigin="IamCrazy">
    

    有趣的是,如果您跳过 crossorigin 属性,CORS 行为将完全禁用。例如:

    <script src="https://stackoverflow.com/foo.js">
    

    这个标签将运行脚本而不进行任何与 CORS 相关的检查。实际上,没有crossorigin 属性会使浏览器完全跳过Origin HTTP 标头。

    无论您的crossoriginanonymous 还是use-credentials,请求的Origin 仍必须与响应的Access-Control-Allow-Origin 匹配。否则没有运气 - 脚本永远不会被触发。

    来源:HTTP access control (CORS) on Mozilla Developer Network

    【讨论】:

    • 这是错误的。或者是正确的,但 Chrome 的实现与此不匹配。
    • @WilliamEntriken 在 Chrome 中有什么特别的不同之处?我今天再次测试它,看起来我的答案仍然正确。 crossorigin只有三种行为:允许所有(根本没有属性),发送凭据(crossorigin="use-credentials")和跳过凭据(use-credentials以外的任何值),正式anonymous,非正式可以是任何东西,包括空值。
    • 在我链接的文档中也有非常明确的说明:“无效关键字和空字符串将作为匿名关键字处理。”.
    【解决方案3】:

    这是一个有点旧的线程,但这是我最近偶然发现的。 除了 crossorigin,您还应该确保从中加载脚本的 服务器(在您的示例中 - stackoverflow.com)返回 特定标题

    'Access-Control-Allow-Origin' '*';
    

    只有这样您才能收到有关脚本中发生的错误的完整信息。

    当然,如果您确定允许使用哪个 url,则应该使用它而不是 asterix '*'

    【讨论】:

    • 除非您知道自己在做什么,否则不要使用通配符 *。更好的说法是:Access-Control-Allow-Origin: https://requestingserver.com 将域替换为请求服务器的域。
    • 具有 * 和具有请求服务器的值之间的安全值有什么区别?我没有看到任何价值提升。
    • “*”允许所有可能的服务器,而不是一个特定的值。
    • 我知道。我的问题是没有允许凭据:是的,这里有什么风险?
    • 而 Flimm 的建议是:“用请求服务器的域替换它”,这似乎并没有在安全性方面提供任何价值升级。事实上,反映请求的来源(加上允许凭据:true)可能会在使用 cookie 进行身份验证的服务器中引入安全漏洞
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2021-04-16
    • 2018-02-26
    • 2019-11-19
    相关资源
    最近更新 更多