我们的网站在使用最新版本的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规范有什么变化吗?
答案 0 :(得分:13)
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分配设置(“行为”标签):
我们通过具有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已经破裂。问题是双重的。
Vary: Origin
标头,因此在*
值使用AllowedOrigin
时出现问题,并且只会缓存多个AllowedOrigin
值中的第一个最后,这两个问题使得S3 + CloudFront成为使用CORS和(快速)CDN解决方案的难以为继的解决方案 - 至少是开箱即用的。防弹解决方案是创建一个简单的应用程序,代理S3和CloudFront之间的请求,始终添加必需的CORS标头,以便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标头拉入,修复后续的跨源请求。