我从两个不同的域访问 CloudFront。 我将 S3 配置为允许来自两个域的跨源。 来自 mydomain1 的页面将正确获取数据,然后来自 mydomain2 的页面将正确发送请求:
> origin: https://mydomain2
CloudFront 回复如下:
< content-type: application/json
< content-length: 65
< date: Fri, 04 Dec 2020 22:45:50 GMT
< access-control-allow-origin: https://mydomain1
< access-control-allow-methods: GET, PUT
< access-control-allow-credentials: true
< accept-ranges: bytes
< server: AmazonS3
< x-cache: Hit from cloudfront
当然,浏览器阻止了这个请求,因为允许的来源不匹配
我最初以为我的源请求策略错误,但不是,我使用的是 Managed-CORS-S3Origin,它具有正确的name,我检查了它,它说它正在沿着 Origin 标头传递到 S3 原点— 内容分发业务中的“起源”的含义与 HTTP 业务中的含义非常不同,这一事实并没有使问题变得更容易。
但显然,Access-Control-Allow-Origin 响应标头的值由于某种原因被缓存。
因为 AWS 的人想杀了我,所以 CloudFront 缓存附加了两种不同的策略。
其中一个是源请求策略,它控制从 CloudFront 传递到 S3 的标头。 这是自动正确设置的,以传递 Origin 标头。
另一个是缓存策略,它选择使用哪些标头来形成缓存密钥,在本例中不包括 Origin。
这是简直是疯了。 缓存键是 CloudFront 之类的 CDN 如何确定两个请求足够相似,以便它也可以将第一个请求的响应重放为第二个请求的响应。
好吧,也许某个地方有some系统需要标头但不关心该值,因此CloudFront应该通过第一个请求传递标头,然后缓存响应来满足每个后续请求,而不管标头如何.
但是大多数,99.9%的时间,服务器需要标头,因为它将使用标头的值来创建响应,并且不同的标头值会引发不同的响应。当然,S3 和 Origin 标头就是这种情况,因为 S3 将 Origin 请求标头的值复制到响应的 Access-Control-Allow-Origin 标头中。
因此,如果您选择 Managed-CORS-S3Origin 源请求策略来管理具有 S3 源的 CORS,那么在您编写匹配的缓存策略之前,CORS 将无法工作。 没有人告诉你这一点。啊啊啊啊!
有两种方法可以通过 CloudFront 背后的 Amazon S3 启用跨源请求:
第一种方法是让 S3 处理 CORS 标头。这就是您所做的,并且需要
Origin
标头成为 CloudFront 缓存键的一部分才能工作。此方法的缺点是,如果 Origin
标头是缓存键的一部分,则每个 CloudFront 弹出位置需要缓存每个文件的与源数量相同的版本。假设您托管一个 JS 库,其中包含 100 个不同域的不同网站。在这种情况下,每个 CloudFront 位置将需要缓存 100 个版本的库,并且缓存将需要更长的时间来填充。来自每个域的初始请求将始终是缓存未命中。
第二种方法是让 CloudFront 处理 CORS 标头。您可以按照本文档中的说明创建并附加 CloudFront 响应标头策略:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/creating-response-headers-policies.html 在这种方法中,CloudFront 完全负责处理 CORS 标头,因此无需将
Origin
标头传递到 S3 并将其作为缓存键的一部分包含在内。也无需配置 S3 返回任何 CORS 标头。