正确的S3 + Cloudfront CORS配置?

kat*_*ray 59 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>
Run Code Online (Sandbox Code Playgroud)

CloudFront的

起源

Origin Protocol Policy: Match Viewer

HTTP Port: 80

HTTPS Port: 443
Run Code Online (Sandbox Code Playgroud)

行为

Origin: MY_WEBSITE_URL

Object Caching: Use Origin Cache Headers

Forward Cookies: None

Forward Query Strings: Yes
Run Code Online (Sandbox Code Playgroud)

这里有什么我想念的吗?

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

<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>
Run Code Online (Sandbox Code Playgroud)

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

仍然没有去.

更新:更多信息请求

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

UPDATE

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

img.crossOrigin = '';
Run Code Online (Sandbox Code Playgroud)

但然后图像没有加载,我得到错误:跨源资源共享策略拒绝跨源图像加载.

Bre*_*ett 114

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

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

    <AllowedOrigin>*</ AllowedOrigin>

  2. 在CloudFront - > Distribution - >此行为的行为中,使用Forward Headers:Whiteelist选项并将'Origin'标题列入白名单.

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

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

  • FWIW,我还必须改变缓存行为,以改变"允许的HTTP方法",包括OPTIONS. (6认同)
  • 根据 [AWS 文档](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-cors),您还应该将`Access- Control-Request-Headers` 和 `Access-Control-Request-Method` 如果使用 S3 源并且你想要缓存 `OPTIONS`(通常我相信你会想要)。 (5认同)

Nik*_*kov 40

2022年答案:

  1. 转到您的 S3 存储桶 -> 权限
  2. 向下滚动到跨域资源共享 (CORS)
  3. 适用政策:
[
    {
        "AllowedHeaders": [],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]
Run Code Online (Sandbox Code Playgroud)

这将允许来自所有来源的 GET 请求。根据您的项目需求进行修改。

  1. 转到您的CloudFront 发行版 -> 行为 -> 编辑(在我的例子中,我只有一种行为)

  2. 向下滚动到缓存密钥和源请求

  3. 选择缓存策略和源站请求策略(推荐)

  4. 在源请求策略下- 可选选择CORS-CustomOrigin

  5. 保存更改

完毕!

  • 为什么使用“CORS-CustomOrigin”而不是“CORS-S3Origin”? (4认同)

Chr*_*son 29

补充@ 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应该可行.

  • 何时应该缓存或不缓存OPTIONS响应? (8认同)

小智 19

2023 年 3 月 - 这对我有用。

S3 存储桶配置

S3 存储桶的跨源资源共享 (CORS)策略(存储桶详细信息 > 权限)。调整AllowedOrigins,适合您的项目(您可以在设置测试期间AllowedHeaders使用)。*

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]
Run Code Online (Sandbox Code Playgroud)

适用于存储桶 CORS 的 AWS 控制台

Cloudfront CDN 配置

转到 Cloudfront distribution > 编辑行为(在大多数情况下,每个发行版只有一个)

CDN 行为配置

  • 起源请求策略 Core-CustomOrigin 对我不起作用,如果您的云前端连接到 S3,则选择 CORS-S3Origin 有效。变化立即反映在我身上。 (2认同)

小智 6

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

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


Qui*_*ncy 6

我遵循了AWS文档:

然后我使用 aws cdk 来帮我做这件事。完整源代码在这里: https: //github.com/quincycs/quincymitchell.com

const myBucket = new Bucket(this, 'bucket', {
  bucketName: `prod-${domainName}`,
  cors: [{
    allowedMethods: [HttpMethods.GET],
    allowedOrigins: ['*'],
    allowedHeaders: ['*']
  }],
  enforceSSL: true,
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
  removalPolicy: RemovalPolicy.RETAIN
});
const mycert = Certificate.fromCertificateArn(this, 'certificate', ssmCertArn);

new Distribution(this, 'myDist', {
  defaultBehavior: {
    origin: new S3Origin(myBucket),
    viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
    originRequestPolicy: OriginRequestPolicy.CORS_S3_ORIGIN,
    responseHeadersPolicy: ResponseHeadersPolicy.CORS_ALLOW_ALL_ORIGINS,
    allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS, // needed for cors
    cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS, // needed for cors
  },
  defaultRootObject: 'index.html',
  domainNames: [domainName, `www.${domainName}`],
  certificate: mycert
});
Run Code Online (Sandbox Code Playgroud)


Cym*_*men 5

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

问题

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

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

Access-Control-Allow-Origin: http://example.com
Run Code Online (Sandbox Code Playgroud)

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

Access-Control-Allow-Origin: http://example.com
Run Code Online (Sandbox Code Playgroud)

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

解决方法

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

因此,我们的URL类似于:

http://.../some.png?http_mysite.com
https://.../some.png?https_mysite.com
Run Code Online (Sandbox Code Playgroud)

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

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

在实践中

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

  • +1顶部的更新说明! (2认同)
  • 这可能会有所帮助:http://ryanwood.com/2014/09/03/a-chrome-update-breaks-cdn-fonts/ (2认同)

Ank*_*ham 5

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

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

  2. 请参阅:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html 在此输入图像描述

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

  1. Cloudfront 行为:我假设您已经设置了受信任的密钥组,此时您已经拥有签名的 cookie。但是,您将需要创建自定义缓存策略和源请求策略。在此输入图像描述请参阅以下自定义缓存策略的屏幕截图:在此输入图像描述和原产地请求政策:在此输入图像描述需要注意的是,您需要将这些标头列入白名单:Origin、Access-Control-Request-Method、Access-Control-Allow-Origin、Access-Control-Request-Headers。(您可能会注意到 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"
        ]
    }
]
Run Code Online (Sandbox Code Playgroud)
  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%"
  />
Run Code Online (Sandbox Code Playgroud)