ChatGPT解决这个技术问题 Extra ChatGPT

正确的 S3 + Cloudfront CORS 配置?

我的应用程序将图像存储在 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 实现了完全相同的东西,所以如果您给我更多详细信息,我可以为您提供帮助。

C
Charney Kaye

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

为您的 S3 存储桶设置 CORS 配置,包括 * 在 CloudFront -> 分发 -> 此源的行为 允许的 HTTP 方法:+OPTIONS 缓存的 HTTP 方法 +OPTIONS 基于所选请求标头的缓存:将 Origin 标头列入白名单.在 CloudFront 传播新规则时等待约 20 分钟

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


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

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

详细的步骤如下:

在您的 S3 存储桶中,转到 Permissions -> CORS configuration 在编辑器中为 CORS 添加规则, 规则是重要的。保存配置。在您的 CloudFront 分配中,转到行为 -> 选择一种行为 -> 编辑 根据您是否希望缓存 OPTIONS 响应,根据 AWS,有两种方法:

如果您希望缓存 OPTIONS 响应,请执行以下操作: 选择默认缓存行为设置的选项,以启用缓存 OPTIONS 响应。配置 CloudFront 以转发以下标头:Origin、Access-Control-Request-Headers 和 Access-Control-Request-Method。如果您不希望缓存 OPTIONS 响应,请将 CloudFront 配置为转发 Origin 标头以及您的源所需的任何其他标头

https://i.stack.imgur.com/GuoCh.png

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


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

更新:最近对 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 以某种方式获得了错误的字体缓存记录,事情仍然可以继续工作。


S
Sebastian Brestin

作为对上一个答案的补充,我想分享有关如何启用 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"
A
Ankit Shubham

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

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

https://i.stack.imgur.com/GUIH7.png

Cloudfront 行为:我假设您已经设置了受信任的密钥组,因为此时您已经拥有签名的 cookie。但是,您将需要创建自定义缓存策略和源请求策略。请参阅以下自定义缓存策略的屏幕截图:和来源请求策略:需要注意的是,您需要将这些标头列入白名单:来源、访问控制请求方法、访问控制允许来源、访问控制-请求标头。 (您可能会注意到 Access-Control-Allow-Origin 不在下拉列表中;只需继续输入它!)。此外,允许所有 cookie。 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”]}]

react-player:我正在使用这样的 react-player(注意设置了 forceHLS 选项,但它又是针对我的用例的。我认为这通常不是强制性的)

} width="100%" height="100%" />


J
Jim

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

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

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

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


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

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

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

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

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


Q
Quincy

我遵循了 AWS 文档:

CloudFront-CORS

S3-CORS

然后我使用 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
});

N
Nikolay Dyankov

2022年答案:

转到您的 S3 存储桶 -> 权限向下滚动到跨域资源共享 (CORS) 应用策略:

[
    {
        "AllowedHeaders": [],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

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

转到您的 CloudFront 分配 -> 行为 -> 编辑(在我的情况下,我只有一个行为)向下滚动到缓存键和源请求选择缓存策略和源请求策略(推荐)在源请求策略下 - 可选选择 CORS-CustomOrigin 保存变化

完毕!