使用 <script crossorigin='anonymous'>,为什么脚本"blocked by CORS policy"?



使用谷歌浏览器或火狐,如果我尝试加载以下 HTML:

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

我收到这样的 CORS 错误:

CORS 策略已阻止从源"https://stackoverflow.com"访问"https://stackoverflow.com/foo.js"处的脚本:请求的资源上不存在"访问控制-允许源"标头...

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

这令人惊讶,因为anonymous只是为了阻止发送任何凭据,而脚本标记不应该需要 CORS。是什么原因造成的,我该怎么办?

我对此感到困惑了一段时间。以下是我现在的理解:

根据 W3C 的说法,crossorigin属性实际上有三个可能的值:anonymoususe-credentials和只能通过省略属性来访问的"缺失值默认值"。(另一方面,空字符串映射到anonymous。默认值会导致浏览器完全跳过 CORS,这是我期望的正常行为。

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

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属性使浏览器完全跳过OriginHTTP标头。

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

来源:Mozilla 开发者网络上的 HTTP 访问控制 (CORS)

这有点老了,但这是我碰巧遇到的东西,这些天。 除了跨源之外,还应确保从中加载脚本的服务器(在您的示例中 - stackoverflow.com)返回特定的标头

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

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

当然,如果您确定允许哪个URL,您应该使用它而不是星号"*"。

这很令人惊讶,因为匿名只是为了阻止发送任何凭据,而脚本标签不应该需要 CORS。是什么原因造成的

在那里使用"只是"这个词是不正确的。

onerror上看到MDN:

当从不同源加载的脚本中发生错误时,不会报告错误的详细信息以防止泄露信息(请参阅 bug 363897)。相反,报告的错误是"脚本错误"。 在某些浏览器中,可以使用<script>上的crossorigin属性并让服务器发送相应的 CORS HTTP 响应标头来覆盖此行为。

添加任何crossorigin属性值应该允许您执行需要 CORS 权限的操作。对于要向onerror报告有用错误消息的脚本,如上面的引用所示。

这样做的代价是,您现在需要 CORS 权限才能对数据执行任何操作。对于脚本元素,这包括执行脚本(正如您所指出的,通常不需要 CORS 权限)。

anonymoususe-credentials之间的区别在于后者还将

  • 需要预检 OPTIONS 请求才能获得发送凭据(例如任何 cookie)的权限,然后才能对脚本发出 GET 请求
  • 在脚本的 GET 请求中发送任何凭据

我该怎么办?

您可以:

  • 不使用crossorigin属性(该属性会将任何凭据(例如 cookie)发送到服务器,除非它们被浏览器中的第三方 cookie 策略阻止)
  • 使用Access-Control-Allow-Origin响应标头让服务器授予权限
  • 将脚本移动到没有关联凭据的其他域(例如,您可以使用 cookiewww.example.com,而cdn.example.com没有)。

最新更新