最新的Chromium和Google Canary上的Amazon S3的CORS问题

时间:2013-11-27 21:31:59

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

我们的网站在使用最新版本的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”标头。因此,不允许原点“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规范有什么变化吗?

4 个答案:

答案 0 :(得分:13)

亚马逊几个月前发布了针对此问题的解决方案。我们看到当前版本的Chrome&amp; 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
  4. 我们通过具有S3源的CloudFront托管css和静态javascript文件。我们通过引用我们的javascript文件 <script crossorigin="anonymous" src="http://assets.domain.com/app.js">

    修改

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

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

    如果你去了第A页 - &gt;第B页 - &gt;在页面A,我们会得到一个交叉来源拒绝错误。我们采取了延迟加载方法,它解决了我们的问题(再次)。

答案 1 :(得分:10)

很可能,您遇到了S3 / CloudFront / CORS的一个非常着名的问题。我能找到的最佳解决方案是在S3和CloudFront之间安装一个代理应用程序,并在返回时始终为对象添加适当的CORS标头。

在将CORS资产提供给不同的Web浏览器时,S3 + CloudFront已经破裂。问题是双重的。

  • 并非所有浏览器都需要CORS才能使用网络字体和其他静态资源。如果其中一个浏览器发出请求,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)时,您会更频繁地看到它。此外,如果您有单独的开发/暂存/生产环境,则可能会更频繁地遇到多源问题。

答案 2 :(得分:7)

将任何查询参数(例如?cacheblock=true)添加到网址中,如下所示:

而不是:https://somebucket.s3.amazonaws.com/someresource.pdf

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

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

包含查询参数可以防止Chrome中的“行为不当”缓存行为,从而导致Chrome发出预检请求和实际请求的新请求,从而允许在两个请求中都显示正确的标头,从而允许S3回应得当。约。

答案 3 :(得分:3)

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

为了使我们在复杂场景中的测试更糟糕,刷新之间(因为资源加载的顺序?)和其他浏览器似乎并不一致完全一致。

这是有趣的虫子狩猎!似乎只需将crossorigin='anonymous'添加到加载资源的任何标记中,就会强制Chrome将CORS标头拉入,修复后续的跨源请求。