使用本指南可解决浏览器控制台窗口中与 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 协议
由 Zendesk 提供技术支持