使用谷歌浏览器或火狐,如果我尝试加载以下 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
属性实际上有三个可能的值:anonymous
、use-credentials
和只能通过省略属性来访问的"缺失值默认值"。(另一方面,空字符串映射到anonymous
。默认值会导致浏览器完全跳过 CORS,这是我期望的正常行为。
仅当我们关心获取正在加载的脚本的错误信息时,才应使用crossorigin
属性。由于访问此信息需要 CORS 检查,因此资源上必须存在Access-Control-Allow-Origin
标头才能加载。
crossorigin
属性只有两个可能的值:anonymous
或use-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标头。
无论您的crossorigin
是anonymous
还是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 权限)。
anonymous
和use-credentials
之间的区别在于后者还将:
- 需要预检 OPTIONS 请求才能获得发送凭据(例如任何 cookie)的权限,然后才能对脚本发出 GET 请求
- 在脚本的 GET 请求中发送任何凭据
我该怎么办?
您可以:
- 不使用
crossorigin
属性(该属性会将任何凭据(例如 cookie)发送到服务器,除非它们被浏览器中的第三方 cookie 策略阻止) - 使用
Access-Control-Allow-Origin
响应标头让服务器授予权限 - 将脚本移动到没有关联凭据的其他域(例如,您可以使用 cookie
www.example.com
,而cdn.example.com
没有)。