【问题标题】:Correct S3 + Cloudfront CORS Configuration?正确的 S3 + Cloudfront CORS 配置?
【发布时间】:2012-09-03 16:51:30
【问题描述】:

我的应用程序将图像存储在 S3 上,然后通过 Cloudfront 代理它们。我很高兴能够使用新的 S3 CORS 支持,这样我就可以使用 HTML5 画布方法(具有跨域策略),但似乎无法正确配置我的 S3 和 Cloudfront。当我尝试将图像转换为画布元素时,仍然遇到“未捕获的错误: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>

云端

起源

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 = '';

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

【问题讨论】:

  • 您可以在这里发布您的发帖请求吗?就像您在上传到 s3 时在发布请求中传递的策略和参数一样。
  • 为什么是 POST 请求而不是 GET 请求?
  • 好的,你能提供有关获取请求的信息吗?
  • 它只是一个 'src' - 还有其他我应该格式化请求的方法吗?
  • 您可以将图像存储在 s3 上吗?这是您在检索图像时遇到的问题吗?尝试使用 s3 对象的详细信息部分的链接。它将类似于 s3.amazonaws.com/<bucketname>... 并检查您是否仍然收到错误。我使用 CORS 实现了完全相同的东西,所以如果您给我更多详细信息,我可以为您提供帮助。

标签: amazon-s3 cors amazon-cloudfront


【解决方案1】:

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

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

    &lt;AllowedOrigin&gt;*&lt;/AllowedOrigin&gt;

  2. 在 CloudFront -> 分发 -> 此源的行为

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

现在您的 CloudFront 分配应该为不同的客户端 Origin 标头缓存不同的响应(使用适当的 CORS 标头)。

【讨论】:

  • 不错。这看起来也解决了通过 HTTP 和 HTTPS 和 CORS 提供资产的问题。
  • FWIW,我还必须将缓存行为更改为因“允许的 HTTP 方法”而异,包括 OPTIONS。
  • 您少了一步。浏览器将发送一个 OPTIONS 请求来验证是否允许 Origin 标头。因此,您应该单击“GET, HEAD, OPTIONS”,而不仅仅是默认的“GET, HEAD”,确保选项被缓存(否则 Origin 将始终相同!)
  • 根据AWS documentation on this,如果使用 S3 源并且您希望缓存 OPTIONS(通常我相信您会想要),您还应该将 Access-Control-Request-HeadersAccess-Control-Request-Method 列入白名单。跨度>
  • 有时您可能需要在本地测试浏览器中重置缓存。修复对我有用,但由于缓存问题未能传播到我的浏览器:)
【解决方案2】:

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

详细步骤如下:

  1. 在您的 S3 存储桶中转到 权限 -> CORS 配置
  2. 在编辑器中为CORS添加规则,&lt;AllowedOrigin&gt;规则很重要。保存配置。
  3. 在您的 CloudFront 分配中,转到 行为 -> 选择一种行为 -> 编辑
  4. 根据您是否要缓存 OPTIONS 响应,根据 AWS 有两种方法:
  • 如果您希望缓存 OPTIONS 响应,请执行以下操作:
    • 选择启用缓存 OPTIONS 响应的默认缓存行为设置选项。
    • 配置 CloudFront 以转发以下标头:Origin、Access-Control-Request-Headers 和 Access-Control-Request-Method。
  • 如果您不希望缓存 OPTIONS 响应,请配置 CloudFront 转发 Origin 标头以及所需的任何其他标头 按你的出身

使用来自 CloudFront 和 S3 的 CORS 应该可以工作。

【讨论】:

  • 何时应该缓存或不缓存 OPTIONS 响应?
  • 即使存储桶策略仅向云端分发授予读取权限,这也应该有效,对吧?添加此内容是因为您突出显示图像中的公共权限。
  • 天啊,非常感谢您的回答。几个月来,我们一直在错误地运行我们的云端。巨大的道具!
  • 请记住,在测试您的更改是否有效时,您需要在请求中发送“Origin: ”标头,否则您将无法获得新标头。跨度>
【解决方案3】:

更新:最近对 CloudFront 的更改不再适用。伊皮!有关详细信息,请参阅其他回复。我将这里留给上下文/历史。

问题

CloudFront 不支持 CORS 100%。问题是 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。诀窍是附加一个不同的唯一查询字符串,以便每个来源有一个缓存记录。

所以我们的 URL 应该是这样的:

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

这种方法可行,但任何人都可以通过交换查询字符串使您的网站运行不佳。有可能吗?可能不会,但调试这个问题很麻烦。

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

实践中

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

【讨论】:

【解决方案4】:

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

此外,在测试您的更改时,除了 CloudFront 部署延迟之外,您应该考虑的是浏览器缓存。我建议在测试您的更改时使用不同的会话进行隐身。

【讨论】:

  • 谢谢!那个演练真的很有用。尤其是你可以用来测试配置是否正确的 curl 命令:curl -H "origin: example.com" -v "https://www.anything.net/video/call/System.generateId.dwr"
【解决方案5】:

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

  1. 将自定义域分配给 cloudfront,以便自定义域是运行应用前端的子域。在 OP 的情况下,他使用的是 localhost:3000;很可能他正在测试他的开发设置,但他必须在某个域部署这个应用程序:让我们称之为“myapp.com”。因此,他可以分配一个自定义域,例如 cdn.myapp.com 以指向 blah.cloudfront.net。您需要为新的自定义域创建/导入自定义 SSL 证书;默认的云端证书不起作用。

  2. 参考这个:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html

在 Cloudfront Distribution 快照中,第一行没有自定义域,因此 CNAME 列为空。第二个是有一个自定义域,因此我们在那里打印了一个。您可以通过这种方式验证您的自定义域是否已指向云端分发。

  1. Cloudfront 行为:我假设您已经设置了受信任的密钥组,因为此时您已经拥有签名的 cookie。但是,您将需要创建自定义缓存策略和源请求策略。 见下面自定义缓存策略的截图:和源请求策略: 需要注意的是,您需要将这些 Headers 列入白名单:Origin、Access-Control-Request-Method、Access-控制允许来源,访问控制请求标头。 (您可能会注意到 Access-Control-Allow-Origin 不在下拉列表中;只需继续输入它!)。另外,允许所有 cookie。

  2. 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】:

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

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

    回答了我关于 CORS、S3 和 Cloudfront 的一些问题。

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

    【讨论】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-03
      • 2019-02-09
      • 2015-01-08
      • 2017-12-30
      • 2014-09-29
      • 2016-07-23
      • 2016-06-21
      • 2017-12-16
      相关资源
      最近更新 更多