我遇到了一个非常奇怪的问题,似乎无法解决。我配置了一个私有 CloudFront 分发版来提供来自私有 S3 存储桶的内容。我正在使用签名的 cookie 来授予对文件的访问权限。我还从浏览器对文件发出跨源请求,因此我需要允许凭据发送 cookie。我配置了一个自定义响应标头策略来执行此操作(我将其设置为将 Access-Control-Allow-Credentials 设置为 true,明确将 Access-Control-Allow-Origin 设置为我想要的域,并适当地设置 Access-Control-Allow-Methods / Access-Control-Max-Age,并将其设置为源覆盖),并且我还设置了一个自定义缓存策略以根据源和访问控制标头进行缓存。
此 cURL 命令未给出正确的响应:
curl -v -H "origin: https://my-subdomain.my-domain.com" -H "cookie: CloudFront-Key-Pair-Id=MyKeyPairID; CloudFront-Policy=Base64EncodedPolicy; CloudFront-Signature=SignedPolicy" https://my-other-subdomain.my-domain.com/key/to/my/private/file.txt
其结果如下:
< HTTP/1.1 200 OK
< Content-Type: application/octet-stream
< Content-Length: 576
< Connection: keep-alive
< Date: Fri, 18 Feb 2022 18:34:09 GMT
< Last-Modified: Thu, 16 Dec 2021 14:45:12 GMT
< ETag: "a50884915242f9876bea4bb633963191"
< Accept-Ranges: bytes
< Server: AmazonS3
< Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
< Access-Control-Allow-Origin: https://my-subdomain.my-domain.com
< Vary: Origin
< X-Cache: Hit from cloudfront
< Via: 1.1 redacted.cloudfront.net (CloudFront)
< X-Amz-Cf-Pop: EWR50-C1
< X-Amz-Cf-Id: JxMbPWHeQr0a9AAlf9PI5ksF6xGKVWL1LvpEC9XEoR_PVuVgiJ5zGA==
< Age: 626
注意缺少的Access-Control-Allow-Credentials
标题。
但是,此命令产生了正确的响应:
curl -v -H "X-some-header: nonsense" -H "origin: https://my-subdomain.my-domain.com" -H "cookie: CloudFront-Key-Pair-Id=MyKeyPairID; CloudFront-Policy=Base64EncodedPolicy; CloudFront-Signature=SignedPolicy" https://my-other-subdomain.my-domain.com/key/to/my/private/file.txt
返回:
< HTTP/1.1 200 OK
< Content-Type: application/octet-stream
< Content-Length: 576
< Connection: keep-alive
< Date: Fri, 18 Feb 2022 18:34:09 GMT
< Last-Modified: Thu, 16 Dec 2021 14:45:12 GMT
< ETag: "a50884915242f9876bea4bb633963191"
< Accept-Ranges: bytes
< Server: AmazonS3
< Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: https://my-subdomain.my-domain.com
< Vary: Origin
< X-Cache: Hit from cloudfront
< Via: 1.1 redacted.cloudfront.net (CloudFront)
< X-Amz-Cf-Pop: EWR50-C1
< X-Amz-Cf-Id: pUSouCDwLH5Zu6-NBUZqKrb5kY407GLqXXtH4EK2-Th0Z9zZNb54ag==
< Age: 693
这次,Access-Control-Allow-Credentials
标头正确。我不知道我可能配置错误导致这种情况,也不知道为什么会发生这种情况。任何见解都将不胜感激,任何配置或测试输出需要,请告诉我。
谢谢
编辑:
经过反复尝试,我确定响应标头策略上的源覆盖设置导致了问题。当该设置设置为 true 时,除非您在请求中发送了一些无关的标头,否则它不会发送 Access-Control-Allow-Credentials 标头。这是一个问题,因为它还会导致浏览器中出现不必要的预检请求。
关闭该设置,然后将我的 S3 Bucket 的 CORS 配置为如下所示,即可修复此问题:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"https://*",
"http://*"
],
"ExposeHeaders": [
"ETag"
]
}
]
不过,我仍然很好奇,我是否误解了原点覆盖设置,是否有办法正确地做到这一点,或者这是否是 CloudFront 中的某种错误
编辑2:
来源请求策略:AWS Managed CORS-S3Oriign(我尝试过这个策略,但没有策略,结果相同)
缓存策略:基于 Origin 和访问控制标头的自定义缓存策略,还尝试了标准托管 CacheOptimized 策略和 NoCache 策略,以确保没有凭据的请求不会卡在缓存中。还尝试手动使缓存无效,看看命中或未命中是否有区别,结果没有区别。
响应标头策略:自定义以允许凭据,这是原始配置。我最终将原点覆盖设置为 false,如果我重新配置 S3 CORS 策略来设置标头,一切就开始正常工作了。我在下面有一个随机值,Access-Control-Allow-Headers
因为无论出于什么原因,我都不允许将该字段留空。发送的随机标头不必与此处设置的标头匹配才能返回凭据标头,但它必须匹配才能通过浏览器的预检检查。我还对公开标头设置进行了一些调整,但没有任何帮助。
进一步注意,一旦我让 S3 正确设置 CORS 标头,我就可以完全删除响应标头策略,但我必须保留自定义缓存策略,否则不同的来源可能会获得错误的标头。这也不太理想,因为我将让用户从不同的来源访问这些文件,并且我相信如果响应标头策略正常工作,它将在从缓存中提取后设置标头,而不是缓存标头(但我可能错了)。似乎我唯一的其他选择是在响应上运行一些 CF 函数,但这会产生额外的成本和开销,而正常运行的响应标头策略将是免费且更高效的。
但非常奇怪的是,即使 S3 正确设置了 CORS 标头,如果我使用带有源覆盖 true 的响应标头策略,它仍然会在没有附加随机标头的情况下破坏响应。