AWS:如何在S3 CORS配置中允许多个域?

时间:2016-01-05 15:25:54

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

我的许多网站都遇到过依赖S3作为Cloudfront原点的问题。但是,我在允许多个域(而不是允许全局*)方面存在问题。

我已按照文档here(第一个配置)进行操作。并在这里和那里找到了一些其他随机的SO或论坛答案(第二个配置)

感谢任何帮助。

我设置的CORS规则如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>https://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>http://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://staging.example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>http://example.dev</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>https://example.com</AllowedOrigin>
        <AllowedOrigin>http://example.com</AllowedOrigin>
        <AllowedOrigin>https://staging.example.com</AllowedOrigin>
        <AllowedOrigin>http://example.dev</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

我一直在 https://example.com所有网站上收到字体来源错误:

  

来自原点的字体&#39; http://CLOUDFRONTURL&#39;已被跨源资源共享策略阻止加载:No&#39; Access-Control-Allow-Origin&#39;标头出现在请求的资源上。起源&#39; http://example.dev&#39;因此不允许访问。

  

来自原点的字体&#39; http://CLOUDFRONTURL&#39;已被跨源资源共享策略阻止加载:“访问控制 - 允许 - 来源”&#39;标头的值为&#39; https://example.com&#39;这不等于提供的原产地。起源&#39; http://example.dev&#39;因此不允许访问。

2 个答案:

答案 0 :(得分:4)

CloudFront根据已从浏览器转发到源服务器的请求标头的所有来缓存对象 - 而不仅仅是路径。

对于要从缓存提供的响应,必须返回该响应以响应之前涉及完全相同请求标头的请求。

这是因为,至少原则上,不同的标头可以触发服务器的不同行为,并且行为良好的缓存不能自行承担。

为了提高对象的可缓存性而不影响其提供正确的响应的能力(即,原始服务器为给定请求返回的响应相同),CloudFront几乎删除了请求标头之前将请求转发到源,并在执行缓存查找时使用剥离的请求版本。

当原始服务器是“自定义”(即非S3)源时,您可以选择要转发到源服务器的标头。

但是当原始服务器是S3时,您仍然可以选择,但只有三个可以选择转发......并且它们都与CORS相关。

  

[使用S3原点],您可以将CloudFront配置为仅基于三个标题转发和缓存对象:Access-Control-Request-HeadersAccess-Control-Request-MethodOrigin。转发这些标头允许CloudFront为启用跨源资源共享(CORS)的网站分发内容。您无法将CloudFront配置为将自定义标头转发到Amazon S3。

     

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web

如果Origin:标头至少没有转发,那么S3将无法对其做出反应。启用此标头的转发意味着S3不仅会看到它,并且可能因为存储桶上的CORS配置而修改其响应,而且同一对象的Origin:的每个变体将导致S3返回的不同(和正确)响应,并由CloudFront为将来的匹配请求进行缓存。

CloudFront无法将自定义标头转发到S3,因为这没有任何意义 - 因为S3存储静态内容,响应在其他标头上不会有所不同,因此转发它们将毫无意义并会降低缓存命中率,许多(据称)不同的响应被缓存,但只是为了响应伴随相同标题的请求而提供。

答案 1 :(得分:0)

背景:您的设置

  • 假设您有域 A(例如 dev.mydomain.com)和域 B(例如 www.mydomain.com)。
  • 您的 CDN 位于 cdn.mydomain.com,它位于 CloudFront 上并指向私有 S3 存储桶。
  • 当您通过 /fonts/myfont.woffwww.mydomain.com 请求文件(例如 https://cdn.mydomain.com/fonts/myfont.woff,需要 CORS,per MDN)时,可以访问这些文件。 (到目前为止,请参阅 my answer here 了解如何设置。)

要求(仅针对此问题)

  • 您希望文件仅在请求它的页面(即 cdn.mydomain.com/fonts/myfont.woff 标头)是 要么 Origin dev.mydomain.com
  • 您确实希望在 www.mydomain.com 在此页面上加载您的字体文件(通过您的 CDN URL)时可以访问该文件,以节省他自己的带宽/托管成本;更不用说网络钓鱼和此类风险了!

问题

默认情况下,CloudFront 会缓存任何传入请求的响应。这就是 CDN 的全部意义所在。

但是,第一次(在失效之后)请求来自两个域中的任何一个域对某个文件(例如 junk-cheap.com),CloudFront 将此文件的响应缓存为 /fonts/myfont.woff。所以缓存键默认几乎只有路径。

现在,当来自域 B 的请求针对同一个文件时,对象的缓存响应“允许域”是针对域 A 的,这不匹配导致 CORS 错误。

解决方案

一个简单的解决方案是告诉 CloudFront 将 { "/fonts/myfont.woff": "<this response object with headers>"} 合并到缓存键中。因此,在上面的示例中,缓存类似于 Origin

您可以通过创建一个接受 { ["/fonts/myfont.woff", "Origin: www.mydomain.com"]: <response for www.mydomain.com only>, ... } 标头的新缓存策略来实现此目的:

enter image description here

然后根据您的行为进行设置。

enter image description here

现在,使分发无效并重试!它应该工作。 :)

祝你好运!