正确的S3 + Cloudfront CORS配置?


78

我的应用程序将图像存储在S3上,然后通过Cloudfront对其进行代理。我很高兴使用新的S3 CORS支持,以便可以使用HTML5 canvas方法(具有跨域策略),但似乎无法正确配置S3和Cloudfront。当我尝试将图像转换为画布元素时,仍然遇到“未捕获的错误:SECURITY_ERR:DOM异常18”。

这是我到目前为止的内容:

S3

<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>MY_WEBSITE_URL</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
  <CORSRule>
    <AllowedOrigin>MY_CLOUDFRONT_URL</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
    </CORSRule>
  </CORSConfiguration>

云前

起源

Origin Protocol Policy: Match Viewer

HTTP Port: 80

HTTPS Port: 443

行为举止

Origin: MY_WEBSITE_URL

Object Caching: Use Origin Cache Headers

Forward Cookies: None

Forward Query Strings: Yes

我在这里想念什么吗?

更新:刚刚尝试将标题更改为

<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>

基于此问题的Amazon S3 CORS(跨域资源共享)和Firefox跨域字体加载

还是不走。

更新:有关请求的更多信息

Request
URL:https://d1r5nr1emc2xy5.cloudfront.net/uploaded/BAhbBlsHOgZmSSImMjAxMi8wOS8xMC8xOC81NC80Mi85NC9ncmFzczMuanBnBjoGRVQ/32c0cee8
Request Method:GET
Status Code:200 OK (from cache)

更新

我认为我的要求可能不正确,因此我尝试通过以下方式启用CORS:

img.crossOrigin = '';

但随后图像无法加载,并且出现错误:跨域资源共享策略拒绝了跨域图像加载。


您可以在这里发布您的发帖请求吗?就像您上传到s3时在后期请求中传递的政策和参数一样。
Avichal Badaya 2012年

为什么POST请求而不是GET请求?
kateray 2012年

好的,您可以提供有关获取请求的信息吗?
Avichal Badaya 2012年

这只是一个“ src”-我应该格式化请求的其他方式吗?
kateray 2012年

您是否可以将图像存储在s3上?这是您在检索图像时遇到的问题吗?尝试使用s3对象的details部分中的链接。它将类似于s3.amazonaws.com/ <bucketname> ...,然后检查是否仍然出现错误。我已经使用CORS实现了完全相同的操作,因此,如果您提供更多详细信息,我可以为您提供帮助。
Avichal Badaya 2012年

Answers:


142

2014年6月26日,AWS在CloudFront上发布了适当的Vary:Origin行为,现在您只需

  1. 为您的S3存储桶设置CORS配置,包括

    <AllowedOrigin>*</AllowedOrigin>

  2. 在CloudFront->分配->此来源的行为中

    • 允许的HTTP方法:+ OPTIONS
    • 缓存的HTTP方法+ OPTIONS
    • 基于所选请求Origin标头的缓存:将标头列入白名单。
  3. 等待约20分钟,然后CloudFront传播新规则

现在,您的CloudFront分发应该为不同的客户端Origin头缓存不同的响应(带有正确的CORS头)。


1
真好 这看起来也解决了通过带有CORS的HTTP和HTTPS解决提供资产的问题。

6
FWIW,我还必须更改缓存行为,以通过包括选项在内的“允许的HTTP方法”来改变。
welegan 2014年

1
您错过了一步。浏览器将发送一个OPTIONS请求,以验证是否允许Origin标头。因此,您应该单击'GET,HEAD,OPTIONS',而不仅仅是默认的'GET,HEAD',以确保缓存Options (否则Origin将始终相同!)
Lee Benson

2
根据关于此AWS文档,您还应该将白名单Access-Control-Request-Headers以及Access-Control-Request-Method如果使用S3来源并且想要OPTIONS缓存(通常我相信您会想要)。
用户

1
有时,您可能需要在本地测试浏览器中重置缓存。该修复程序对我
有用

55

补充@Brett的答案。有AWS文档页面详细介绍了上CloudFront的CORSS3上CORS

具体步骤如下:

  1. 在您的S3存储桶中,转到权限-> CORS配置
  2. 在编辑器中为CORS添加规则,该<AllowedOrigin>规则很重要。保存配置。 在此处输入图片说明
  3. 在您的CloudFront分配中,转到行为->选择行为->编辑
  4. 根据您是否要OPTIONS缓存响应,根据AWS,有两种方法:
  • 如果要缓存OPTIONS响应,请执行以下操作:
    • 选择默认缓存行为设置的选项,这些设置启用对OPTIONS响应的缓存。
    • 配置CloudFront以转发以下标头:Origin,Access-Control-Request-Headers和Access-Control-Request-Method。
  • 如果您不希望缓存OPTIONS响应,则将CloudFront配置为转发Origin标头以及源要求的其他标头

在此处输入图片说明

有了CloudFront,带有S3的CORS应该可以工作了。


14
何时应该缓存或不缓存OPTIONS响应?
Fabien Snauwaert,

1
即使存储桶策略仅向Cloudfront分发授予读取权限,这也应该起作用,对吗?由于您突出显示图像中的公共权限,因此添加了此内容。
克里斯·奥德尼(ChrisOdney),

天哪,非常感谢您的回答。几个月来,我们一直在错误地运行Cloudfront。巨大的道具!
卡帕杰

请记住,在进行测试以查看您的更改是否有效时,您需要在请求中发送“ Origin:<some host>”标头,否则您将无法获得新标头。
Kurt

6

更新:CloudFront上的最新更改不再适用。pp!有关详细信息,请参见其他响应。我将其保留在此处以用于上下文/历史记录。

问题

CloudFront不支持100%的CORS。问题是CloudFront如何缓存对请求的响应。此后,对同一URL的任何其他请求都将导致缓存的请求,无论来源如何。关于它的关键部分是它包括来自起点的响应头。

CloudFront缓存了任何内容之前的第一个请求Origin: http://example.com的响应标头为:

Access-Control-Allow-Origin: http://example.com

来自的第二个请求Origin: https://example.com(请注意,它是HTTPS而不是HTTP)也具有以下响应标头:

Access-Control-Allow-Origin: http://example.com

因为那是CloudFront为URL缓存的内容。这是无效的-浏览器控制台(至少在Chrome中)将显示CORS违规消息,并且一切都会中断。

解决方法

建议的解决方法是对不同的来源使用不同的URL。诀窍是要添加一个唯一的查询字符串,该字符串要有所不同,以便每个源都存在一个缓存的记录。

因此,我们的网址将类似于:

http://.../some.png?http_mysite.com
https://.../some.png?https_mysite.com

这种工作方式有效,但是任何人都可以通过交换查询字符串来使您的网站无法正常工作。那可能吗?可能不是,但是调试此问题非常麻烦。

正确的解决方法是在CloudFront完全支持CORS之前,不要将CloudFront与CORS一起使用。

在实践中

如果您将CloudFront用于CORS,请使用其他方法,而在CORS不使用时,该方法将起作用。这并非总是一种选择,但现在我正在使用JavaScript动态加载字体。如果对CloudFront的基于CORS的请求失败,我将退回到字体的服务器端代理(不跨源)。这样,即使CloudFront以某种方式获得了不良的字体缓存记录,事情仍然可以正常进行。



2

不完全确定您的问题是什么,但是:

https://forums.aws.amazon.com/thread.jspa?messageID=377513

使用CORS,S3和Cloudfront回答了我的一些问题。

我还发现,存储桶中的某些资产将返回正确的CORS标头,而某些资产则不会。在使资产无效之后,它们都以正确的标头返回,不确定为什么有些需要无效,而另一些则没有,因为它们是在同一时间,相同类型,相同存储桶中上传的:(


4
吉姆:您发布的链接应该回答您自己的问题!无效后,您得到了不同的结果,可能是因为您有多个AllowedOrigin选项(或*),并且CloudFront缓存了首先请求的Origin标头。
philfreo

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.