【问题标题】:CORS problems with Amazon S3 on the latest Chomium and Google Canary最新 Chromium 和 Google Canary 上的 Amazon S3 的 CORS 问题
【发布时间】:2013-12-13 17:51:55
【问题描述】:

我们的网站在使用最新版本的 Chromium(版本 33.0.1722.0 - 237596)和 Chrome Canary 的 Amazon S3 存储桶上加载 CSS 和 JS 资源时遇到问题。 它适用于任何其他浏览器,包括当前的 Chrome (31.0.1650.57)。

错误是:

来自“https://mybucket.s3.amazonaws.com”的脚本已被跨域资源共享策略阻止加载:请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'https://app.example.com' 因此不允许访问。

我们在资源桶上的 S3 CORS 配置是:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>300000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

这是 Chromium 的错误吗? 最新的 CORS 规范有什么变化吗?

【问题讨论】:

  • 是否有可能由特定浏览器发送的另一个标头也需要包含在 中?或者可能是 *?
  • 我正在阅读并阅读了有关 * 的信息。我在 Stackoverflow 上的另一个 QA 中读到,根据规范,您不能在 中使用“*”(我没有检查规范)。以防万一我尝试添加它但我没有看到任何变化(即错误仍然存​​在)。
  • 我也有同样的问题,请问您是怎么​​解决这个问题的?

标签: google-chrome amazon-web-services amazon-s3 cors


【解决方案1】:

您很可能在使用 S3/CloudFront/CORS 时遇到了一个众所周知的问题。我能找到的最佳解决方案是拥有一个在 S3 和 CloudFront 之间代理的应用程序,始终在对象返回时向它们添加适当的 CORS 标头。

在将 CORS 资产提供给不同的 Web 浏览器时,S3 + CloudFront 被破坏了。问题有两个方面。

  • 并非所有浏览器都需要 CORS 用于 Web 字体和其他静态资产。如果其中一个浏览器发出请求,S3 将不会发送 CORS 标头,CloudFront 将缓存(无用的)响应。
  • CloudFront 不支持 Vary: Origin 标头,因此在将 * 用于 AllowedOrigin 值时会出现问题,并且只会缓存多个 AllowedOrigin 值中的第一个。

最后,这两个问题使 S3 + CloudFront 成为将 CORS 与(快速)CDN 解决方案结合使用的站不住脚的解决方案——至少,开箱即用。防弹解决方案是创建一个简单的应用程序来代理 S3 和 CloudFront 之间的请求,始终添加必要的 CORS 标头,以便 CloudFront 始终缓存它们。

请求“冷”缓存

  • ← 浏览器从 CloudFront 请求静态资产。
  • ← CloudFront 未命中,并命中其源服务器(代理应用程序)。
  • ← 代理应用将请求传递给 S3。
  • → S3 响应代理应用程序。
  • → 代理应用程序添加正确的 CORS 标头(无论 S3 是否已发送它们)。代理应用程序响应 CloudFront。
  • → CloudFront 缓存结果并响应浏览器。

针对“暖”缓存的请求

  • ← 浏览器从 CloudFront 请求静态资产。
  • → CloudFront 命中并响应浏览器。

是的,这是一个众所周知的普遍问题:

我可以说我们的 S3 和 CloudFront 团队非常了解这里讨论的问题。通过编写一个可以充当 S3 和 CloudFront 之间代理的简单应用程序,您可以在 CloudFront 缓存它们之前手动注入所有正确的 CORS 响应标头。

如果您始终使用 Firefox,那么您可能不会注意到这个问题 - CloudFront 将始终缓存您启用 CORS 的响应。如果您主要在 Safari 或 Chrome 中工作,那么当您切换回需要这些标头的浏览器(Firefox 和 IE)时,您会更频繁地看到它。此外,如果您有单独的开发/暂存/生产环境,您可能会更频繁地遇到多源问题。

【讨论】:

  • 这个“众所周知的 S3/CloudFront/CORS 问题”记录在哪里?以及为什么它在当前的 Chrome 而不是 Chrome Canary 中运行良好?
  • 规范说网络字体应该使用 CORS。到目前为止,IE 和 Firefox 是唯一实现该规范的。 Safari、Chrome 和 Opera 没有。 Chrome(以及相应的 Opera)可能正在更改其实现以遵循规范。
  • 当前版本的火狐没有问题。
  • 确实如此。需要更多空间来解释,所以请参阅我的后续答案。
  • 这是个好东西。关于我的问题:(1)我们不使用 CloudFront。 (2) 我们的页面适用于当前版本的 Chrome 和 Firefox。不是最新的。 (3) 我在 Chromium 上发现了一个错误,他们目前正在查看它。这可能是一个回归问题。
【解决方案2】:

几个月前,亚马逊发布了针对此问题的修复程序。我们在当前版本的 Chrome 和 Safari 中看到了错误(没有检查 Firefox)。对于仍然遇到此问题的任何人,请尝试以下配置:

S3 存储桶 CORS 政策:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

CloudFront 分配设置(行为选项卡):

  1. 允许的 HTTP 方法:GET、HEAD、OPTIONS
  2. 转发标头:白名单
  3. 白名单标头:Origin、Access-Control-Request-Headers、Access-Control-Request-Method

我们通过具有 S3 源的 CloudFront 托管 css 和静态 javascript 文件。我们通过以下方式引用我们的 javascript 文件 &lt;script crossorigin="anonymous" src="http://assets.domain.com/app.js"&gt;.

编辑

我们开始在 Safari 10.1.2 中再次看到此问题。事实证明,我们以两种方式访问​​ Javascript 文件...

通过&lt;script crossorigin="anonymous" src="http://assets.domain.com/app.js"&gt; 在页面 A。 通过$.ajax() 在页面 B 上(因此它是延迟加载的)。

如果您转到页面 A -> 页面 B -> 页面 A,我们会收到跨源被拒绝错误。我们取消了延迟加载方法,它(再次)解决了我们的问题。

【讨论】:

  • 这是有道理的,但你必须等待它传播吗?如果有,需要多长时间?我知道有一个默认 TTL 设置是 24 小时(默认),这是您需要等待此更改生效的时间吗?
  • 您只需等待 Cloudfront 分发设置传播到所有边缘服务器。我们花了 15-20 分钟才重新上线。
【解决方案3】:

想用另一种理论来解决这个老问题:Chrome 有一个错误/“功能”,即 been present since at least Aug 2014,如果首次通过正常提取加载资源,则会导致跨域请求失败,显然是因为Chrome 缓存了无 CORS 的资源头,然后拒绝将缓存的资源交给跨域请求。

更糟糕的是,在我们在复杂场景中的测试中,刷新之间甚至不一定完全一致(因为资源加载的顺序?)并且其他浏览器似乎不共享该行为。

这是一次有趣的寻虫之旅!似乎只需将crossorigin='anonymous' 添加到加载资源的任何标签都会强制Chrome 将CORS 标头拉入,从而修复后续的跨域请求。

【讨论】:

  • 这为我指明了正确的方向。在我的例子中,我第一次使用 OBJECT 标签来加载 PDF 文件,所以 crossorigin 属性不可用。因此,在将 PDF url 设置为 OBJECT 之前,我使用常规 ajax 请求获取了 PDF。这解决了我的问题。
【解决方案4】:

在url中添加?cacheblock=true等任意查询参数,如下所示:

代替:https://somebucket.s3.amazonaws.com/someresource.pdf

做:https://somebucket.s3.amazonaws.com/someresource.pdf?cacheblock=true

技术解释我没有完全记下来。但它类似于以下内容:

包含查询参数将防止 Chrome 中的“行为不端”缓存行为,导致 Chrome 为预检请求和实际请求发送新请求,从而允许在两个请求中出现正确的标头,从而允许 S3正确回应。大约。

【讨论】:

  • 这个答案对我帮助很大 :) 非常感谢 :) 我赞成你的答案 :D
  • 对@AnujTBE,这里的主要思想是应该有某种查询参数
  • 谢谢。我搜索了几个小时来解决使用 XMLHttpRequest 设置画布背景的问题!
  • 非常感谢!我花了将近 2 个小时来测试我的应用程序,才意识到是什么导致了问题。现在您还给了我答案,这种行为的根源是什么。就我而言,当我两次加载一张图像时,这个问题发生在我身上。我需要将相同的图像作为纹理加载到 3D 模型中,然后作为 2D 纹理缩略图加载。
猜你喜欢
  • 2016-09-04
  • 2017-12-30
  • 2018-10-05
  • 1970-01-01
  • 2014-09-29
  • 2021-07-21
  • 2017-02-05
  • 2014-09-03
  • 1970-01-01
相关资源
最近更新 更多