使用本指南可解决浏览器控制台窗口中与 Access-Control-Allow-Origin
错误消息相关的常见问题。以下是错误消息示例。
- 加载失败 ...没有标头“Access-Control-Allow-Origin”
- 跨源请求已阻止:同源策略不允许读取远程资源…原因:CORS 标头“Access-Control-Allow-Origin”缺失
- 加载失败 ...对预检请求的响应未通过访问控制检查:请求的资源上没有标头“Access-Control-Allow-Origin”。来源 ... 因此不允许访问
本文章包含以下主题。
错误原因
基于浏览器的 Web 应用程序(例如 Apps framework 应用)尝试进行跨源调用,以从外部网络服务获取共享资源。这称为 CORS 请求(跨源资源共享)。
有一个基于浏览器的 CORS 标准可管理此类跨源调用。当不满足某些条件时,可能会发生错误。
这不一定是缺陷,因为它可能与用户的 Web 应用程序和远程外部服务有意不允许的用例有关。
当一个来源 (www.origin1.com) 调用另一个来源 (www.origin2.com) 时,这称为跨源请求。要使此请求生效,必须满足一定条件。被调用的外部服务 (www.origin2.com) 需要在其响应中返回 HTTP 标头 Access-Control-Allow-Origin
。
如果外部服务未返回此标头,则浏览器将遵守 CORS 规范停止请求,并返回上述错误之一。
故障排除
- 调用(或来源)的起点 URL 是什么?
这有时会包含在错误消息中。 - 被调用的外部服务的 URL 是什么?
这有时会包含在控制台的错误消息中。 - 正在检索什么,为什么?是否为 PNG 文件?脚本、CSS 还是字体文件?检索的具体内容及其用途是什么?
这有助于了解用例以及此远程位置资产的重要性。 - 此外部资源是否需要身份验证才能获取?
如果需要重定向,Access-Control-Allow-Origin
可能无法返回响应标头,调用将失败。直接复制资源的 URL 到新的无痕浏览器标签中。这样可以很好地测试其在一般情况下是否可访问,但并不能保证其在 Web 应用程序的代码中可用。 - 您能否在浏览器的“网络”标签中看到“选项 HTTP 方法调用”?
当跨源请求中存在自定义请求标头、身份验证或其他条件时,浏览器将进行额外的 HTTP 调用。这也称为预检调用。Web 应用程序的代码未明确做到这点。浏览器会在后台创建并将其纳入 CORS 规范标准。
当进行 OPTIONS 调用时,需要在该调用的响应中包含某些值才能成功调用并对资源进行实际 HTTP 调用。如果 OPTIONS 调用失败,则无法检索资源,且浏览器的控制台中应显示 CORS 错误。如果您看到 OPTIONS 调用,请记下来。此外,如果您在 OPTIONS 调用之前看到重定向(状态 302)调用,请记下来。如果重定向发生在 OPTIONS 调用中,则 OPTIONS 调用很可能会失败。这意味着获取资源的调用也将失败,并触发 CORS 错误。 - 获取外部资源有什么用例?
了解为什么要检索到此外部资源。这对于找出解决方法或所需的更改可能很重要。 - 生成 HAR 文件。
获取失败调用的快照以及前后发生的情况,可能有助于解决问题,并避免用户重现问题。可以检查请求和响应中的标头,并识别 OPTIONS 调用和重定向。
可能采取的后续步骤
- 谁拥有外部服务器?或许可以修改服务器,以符合 CORS 规范标准,返回标头
Access-Control-Allow-Origin
。然而,即使服务器是内部控制的,这也并非万能方法。特定外部服务不想共享资源可能有合理理由。如果外部服务器不是内部控制的,则可以与该供应商合作,或找出其他解决方法,但前提是用例有效。 - 应用是否使用 Zendesk App Framework 编写?后端代理服务器可通过
client.request()
调用。要使用此代理,可在 client.request 的设置中设置cors:false
。请注意,“false”也是设置的默认值。代理服务是后端服务,无需遵守基于浏览器的 CORS 规范,因此使用代理进行跨源调用也有可能成功。
这也并非万能方法。代理服务不支持从外部服务检索二进制文件或二进制信息。可能还有其他特定于应用的原因。这也无法解决。 - 资源是否可以直接嵌入 Web 应用程序?与其跨源获取资源,不如考虑将其包含在 Web 应用程序中。这可完全避免跨源调用(因为它现在是本地资源),无论采用何种方法解决 CORS 问题。然而,这并不总能解决问题。例如,有时无法提前知道外部资源 URL,或者资源太大,不适合作为本地资源,或者资源更改过于频繁,无法作为本地静态资源下载。
- 浏览器是什么版本?尽管 CORS 规范已成为标准,浏览器返回的错误消息可能不同。例如,Chrome 返回的控制台消息与 Firefox 不同。
- 有时无法解决。有时来自外部服务的资源请求并不适合在浏览器 Web 应用程序中共享。资源所有者可决定是否共享资源。这不取决于 Web 应用程序,而可能是设计使然。
有关更多信息,请参阅以下资源:
- 维基百科文章:跨源资源共享
- Web.Dev 文章:跨源资源共享 (CORS)
- Mozilla 文章:跨源资源共享 (CORS)
- Mozilla 文章:
OPTIONS
- Fetch 文章:Fetch
- Fetch 文章:CORS 协议