我在使用 AWS Cloudfront 向 Firefox 提供静态资产时遇到了问题。
Chrome 运行完美,但 Firefox 返回 CORS 错误。
如果我执行 curl ,我会得到:
HTTP/1.1 200 OK
Content-Type: application/x-font-opentype
Content-Length: 39420
Connection: keep-alive
Date: Mon, 11 Aug 2014 21:53:50 GMT
Cache-Control: public, max-age=31557600
Expires: Sun, 09 Aug 2015 01:28:02 GMT
Last-Modified: Fri, 08 Aug 2014 19:28:05 GMT
ETag: "9df744bdf9372cf4cff87bb3e2d68fc8"
Accept-Ranges: bytes
Server: AmazonS3
Age: 2743
X-Cache: Hit from cloudfront
Via: 1.1 c445b20dfbf3128d810e975e5d84e2cd.cloudfront.net (CloudFront)
X-Amz-Cf-Id: ...
我认为需要标题:
Access-Control-Allow-Origin: *
有人能帮帮我吗?为什么这个问题只出现在 Firefox 上而不是 Chrome 上?我该如何解决?
答案1
首先,你需要确保将源标头列入白名单:
如果您希望 CloudFront 尊重跨源资源共享设置,请配置 CloudFront 以将 Origin 标头转发到您的源。
另请参阅: http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/
顺便说一句,serverfault/stackoverflow 上有几个类似的问题和很多答案。
答案2
更新:
这些都不再需要了,因为 cloudfront 现在对此有适当的支持。参考: https://aws.amazon.com/about-aws/whats-new/2021/11/amazon-cloudfront-supports-cors-security-custom-http-response-headers/ https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-response-headers.html
先前的回应:
这比接受的答案表明的要复杂一些。
使用 Cloudfront + S3 时,CORS 支持实际上是在 S3 中实现的,其工作原理如下这据亚马逊称:
请求的 Origin 标头必须与 AllowedOrigin 元素匹配。
请求方法(例如,GET 或 PUT)或预检 OPTIONS 请求中的 Access-Control Request-Method 标头必须是 AllowedMethod 元素之一。
预检请求中的请求的 Access-Control-Request-Headers 标头中列出的每个标头都必须与 AllowedHeader 元素匹配。
可能不清楚的是,如果客户端没有发送 Origin 标头,则不会发生此处理。我们在前端使用 Cloudfront,如果您只是托管静态资产,您可能已设置为忽略所有标头。结果是,如果从特定边缘节点对每个文件的第一个请求不包含 Origin 标头,它将缓存没有 Access-Control-Allow-Origin 标头的响应,从而导致 CORS 失败。
结果是,第一个传入的请求将决定所有请求返回哪些标头,直到缓存过期。
有办法可以修复/解决这个问题。
- 根据“Origin”标头启用条件缓存。
如果您仅需要少数或单一来源,这种方法可以很好地工作,但否则您的缓存率可能会变得非常糟糕。
- 使用 Lambda@edge 强制设置标头,每个源(S3)请求只需执行一次。
完全灵活,但增加了开销和成本。
- 将每个请求的“Origin”标头覆盖为虚拟值。
这是通过在“Origin Custom Headers”中插入一些随机域名来实现的。任何像“example.org”这样的内容都可以正常工作,这将导致 S3 处理始终运行,如果配置正确,S3 将返回“Access-Control-Allow-Origin: *”。
这仅在“Access-Control-Allow-Origin:*”情况下才真正有用,并且有点像黑客攻击,但在 cloudfront + S3 上托管静态资产时,它可能是最好的当前解决方案。
答案3
我今天遇到了这个问题,S3 上通过 CloudFront 提供的某些字体文件 (*.woff/*woff2) 丢失了 Access-Control-Allow-Origin 响应标头,导致 Web 浏览器出现 CORS 错误。我估计 Web 爬虫(或其他程序)请求的文件没有 Origin 请求标头,导致缓存的字体副本没有必要的 Access-Control-Allow-Origin 标头。
幸运的是,亚马逊现在推出了 CloudFront Functions,它可以修改请求和响应标头等,作为 Lambda@edge 的低成本替代方案。他们有一个专门用于添加 Origin 标头(如果缺失)的示例函数,如下所示:
https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-origin-header
这对我来说很有效。
答案4
对于一个简单的用例,我构建了一个 CloudFront + S3 原点解决方案,为静态网站提供 HTTPS 和 CORS 设置。
使用新的CloudFront 托管响应标头策略简化 CloudFront 的 CORS 设置。
但是,我在使用这些策略时仍然遇到了 CORS 问题。
我有一个 Ajax 请求,该请求从不同的域发出跨域请求以获取 HTML 资源,并且我会间歇性地收到 CORS 错误,因为响应具有不同域的 Access-Control-Allow-Origin 标头。
看来 CloudFront CDN 正在缓存此标头(尽管使用了所有推荐的“开箱即用”设置)。鉴于此问题的所有历史记录,很难将其归结为正确的原因。
最终,我们意识到我们还在 S3 存储桶上配置了 CORS 策略(允许来源等),这会干扰 CloudFront 策略。虽然在 AWS 控制台中浏览 CloudFront 响应策略设置时看不到它(如果 AWS 添加此功能就好了),但 CloudFront 中的默认 CORS 策略似乎不会覆盖来源设置。因此,S3 CORS 响应被 CloudFront 缓存,从而导致出现问题。
解决方案是清除 S3 权限中的 CORS 策略,并让 CloudFront 处理所有 CORS 标头。
希望这对某些人有帮助(或者我未来的自己能记住这个问题)。