94

我的应用程序将图像存储在 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 = '';

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

4

7 回答 7

167

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

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

    <AllowedOrigin>*</AllowedOrigin>

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

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

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

于 2014-06-27T19:35:16.807 回答
72

补充@Brett 的回答。有 AWS 文档页面详细介绍了 CloudFront上的 CORS和S3上的 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 应该可以工作。

于 2018-09-18T09:28:21.720 回答
6

更新:最近对 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

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

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

在实践中

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

于 2014-06-05T19:04:15.323 回答
4

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

  1. 将自定义域分配给云端,以便自定义域是您的应用程序前端运行的子域。在 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。但是,您将需要创建自定义缓存策略和源请求策略。在此处输入图像描述请参阅以下自定义缓存策略的屏幕截图:在此处输入图像描述和 Origin Request Policy:在此处输入图像描述需要注意的是,您需要将这些标头列入白名单:Origin、Access-Control-Request-Method、Access-Control-Allow-Origin、Access-Control -请求标头。(您可能会注意到 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%"
  />
于 2021-06-10T22:59:21.040 回答
4

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

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

于 2020-07-28T09:53:06.363 回答
2

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

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

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

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

于 2012-09-13T22:17:20.577 回答
0

An additional reason for CORS errors could be the HTTP to HTTPS redirect configured in CloudFront.

According to documentation redirects to different origin are not allowed in CORS requests.

As an example, if you will try to access some URL http://example.com what has cloudfront rule to redirect HTTP to HTTPS, you will get a CORS error, since https://cloudfront.url is considered by the browser as a different origin.

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

于 2021-03-04T12:23:25.757 回答