正确的S3 + Cloudfront CORS配置?

时间:2012-09-10 19:26:17

标签: amazon-s3 cors amazon-cloudfront

我的应用程序将图像存储在S3上,然后通过Cloudfront代理它们。我很高兴使用新的S3 CORS支持,以便我可以使用HTML5 canvas方法(具有跨源策略),但似乎无法正确配置我的S3和Cloudfront。当我尝试将图像转换为canvas元素时,仍然遇到“Uncaught Error:SECURITY_ERR:DOM Exception 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>

的Cloudfront

起源

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 (Cross-Origin Resource Sharing) and Firefox cross-domain font loading

仍然没有。

更新:请求更多信息

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

更新

我想也许我的请求不正确,所以我尝试使用

启用CORS
img.crossOrigin = '';

但是图像没有加载,我收到错误:跨源资源共享策略拒绝跨源图像加载。

7 个答案:

答案 0 :(得分:104)

2014年6月26日,AWS发布了proper Vary: Origin behavior on CloudFront,现在您只需

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

    <AllowedOrigin>*</AllowedOrigin>

  2. 在CloudFront中 - &gt;分发 - &gt;此来源的行为,使用“转发标题:白名单”选项并将Origin标题列入白名单。

  3. 等待~20分钟,而CloudFront传播新规则

  4. 现在,您的CloudFront分配应为不同的客户端Origin标头缓存不同的响应(使用正确的CORS标头)。

答案 1 :(得分:20)

以补充@Brett's answer。有AWS文档页面详细介绍了CORS on CloudFrontCORS on S3

详细步骤如下:

  1. 在您的S3存储桶中,进入权限-> CORS配置
  2. 在编辑器中添加CORS规则,<AllowedOrigin>规则很重要。保存配置。 enter image description here
  3. 在您的CloudFront发行版中,转到行为->选择行为->编辑
  4. 根据是否要缓存OPTIONS个响应,根据AWS,有两种方法:
  
      
  • 如果要缓存OPTIONS响应,请执行以下操作:      
        
    • 选择默认的缓存行为设置选项,以启用对OPTIONS响应的缓存。
    •   
    • 配置CloudFront以转发以下标头:Origin,Access-Control-Request-Header和Access-Control-Request-Method。
    •   
  •   
  • 如果您不希望缓存OPTIONS响应,请配置CloudFront   转发Origin标头以及其他所需的标头   根据您的出身
  •   

enter image description here

借助CloudFront和S3的CORS应该可以正常工作。

答案 2 :(得分:4)

更新:CloudFront最近的更改不再适用。 yippee的!有关详细信息,请参阅其他回复。我将此留在这里了解背景/历史。

<强>问题

CloudFront不支持CORS 100%。问题是CloudFront如何缓存对请求的响应。之后对此相同网址的任何其他请求都会导致缓存请求,无论原点。关键在于它包含来自原点的响应头。

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

这种作品,但任何人都可以通过交换查询字符串使您的网站运作不佳。这可能吗?可能不是调试这个问题是一个很大的麻烦。

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

在实践中

如果您使用CloudFront进行CORS,请回退到另一种方法,当CORS没有时,该方法将起作用。这不是一个选项,但现在我用JavaScript动态加载字体。如果对CloudFront的基于CORS的请求失败,我将回退到字体的服务器端代理(不是交叉源)。这样,即使CloudFront以某种方式获得了字体的错误缓存记录,事情仍然有效。

答案 3 :(得分:2)

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

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

回答了我在CORS,S3和Cloudfront方面遇到的一些问题。

我还发现一个存储桶中的某些资产会返回正确的CORS标头,有些则不会。在使资产无效之后,他们都回来了正确的标题,不知道为什么有些人需要无效而其他人没有因为同时上传,相同类型的同一个桶:(

答案 4 :(得分:2)

作为对上一个答案的补充,我想分享有关如何启用CORS的AWS步骤。我发现它非常有用,它提供了其他链接:https://aws.amazon.com/premiumsupport/knowledge-center/no-access-control-allow-origin-error/

浏览器缓存是测试更改时除CloudFront部署延迟之外还应考虑的事项。建议您在测试更改时使用其他会话进行隐身操作。

答案 5 :(得分:2)

发布一些我为使其工作而做的重要配置:

  1. 将自定义域分配给 cloudfront,使自定义域成为您的应用前端将运行的子域。在 OP 的情况下,他使用的是 localhost:3000;很可能他正在测试他的开发设置,但他必须在某个域中部署这个应用程序:我们称之为“myapp.com”。所以,他可以分配一个自定义域,比如 cdn.myapp.com 指向 blah.cloudfront.net。您需要为新的自定义域创建/导入自定义 SSL 证书;默认的 cloudfront 证书将不起作用。enter image description here 请参阅:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html[![enter 此处的图像描述]2]2 第一个没有自定义域,因此是空的 CNAME柱子。第二个是有一个自定义域,因此我们在那里打印了那个。您可以通过这种方式验证您的自定义域是否指向了 Cloudfront 分发版。
  2. Cloudfront 行为:我假设您已经设置了受信任的密钥组,因为此时您已经有了签名的 cookie。但是,您需要创建自定义缓存策略和源请求策略。 enter image description here 查看自定义缓存策略的以下屏幕截图:enter image description here 和源请求策略:enter image description here 需要注意的是,您需要将这些标头列入白名单:Origin、Access-Control-请求方法、访问控制允许来源、访问控制请求标头。 (您可能会注意到 Access-Control-Allow-Origin 不在下拉列表中;直接输入即可!)。此外,允许所有 cookie。
  3. S3 CORS 配置:转到 S3 存储桶并单击权限选项卡。向下滚动到 CORS 配置。免责声明:我只是粘贴了对我有用的内容。这背后的基本原理是,在我的场景中,这个 S3 将被 CDN 或应用程序访问。我尝试将 '*' 放宽,但 Chrome 上的 CORS 策略抱怨我无法在 AllowedOrigins 中使用通配符条目!
<块引用>
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "GET",
            "HEAD",
            "DELETE"
        ],
        "AllowedOrigins": [
            "cdn.myapp.com",
            "myapp.com",
            "https://cdn.myapp.com",
            "https://myapp.com"
        ],
        "ExposeHeaders": [
            "ETag"
        ]
    }
]
  1. react-player:我正在使用这样的 react-player(注意正在设置 forceHLS 选项,但它再次特定于我的用例。我认为这通常不是强制性的)
<块引用>
<ReactPlayer
    className="react-player"
    url={url}
    controls={controls}
    light={light}
    config={
      {
        file: {
          forceHLS: true,
          hlsOptions: {
            xhrSetup: function (xhr, url) {
              xhr.withCredentials = true; // send cookies
            },
          },
        },
      }
    }
    playIcon={<PlayIcon />}
    width="100%"
    height="100%"
  />

答案 6 :(得分:0)

CORS 错误的另一个原因可能是 CloudFront 中配置的 HTTP 到 HTTPS 重定向。 >

根据文档在 CORS 请求中不允许重定向到不同的来源

例如,如果您尝试访问具有将 HTTP 重定向到 HTTPS 的 cloudfront 规则的某个 URL http://example.com,您将收到 CORS 错误,因为 https://cloudfront .url 被浏览器视为不同的来源。

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSExternalRedirectNotAllowed