【问题标题】:S3 CORS, always send Vary: OriginS3 CORS,始终发送 Vary: Origin
【发布时间】:2015-10-22 07:52:06
【问题描述】:

我在 Cloudfront 后面使用启用了 CORS 的 S3 存储桶。如果客户端使用 Origin 标头发出请求,则 S3(和 cloudfront)以“Vary: Origin”标头响应,但是如果请求是在没有 Origin 标头的情况下发出的,则响应不包含任何 Vary 标头。

这是有问题的,因为我在 img 标签中使用来自 cloudfront/s3 的资源,在这种情况下,浏览器会在没有 Origin 标头的情况下发出请求,然后再对所述图像发出 ajax 请求。然后浏览器使用缓存版本的图像,没有 Access-Control-Allow-Origin 标头,因此拒绝请求。

有什么方法可以让 S3 始终返回“Vary: Origin”标头?

【问题讨论】:

标签: amazon-s3 cors amazon-cloudfront


【解决方案1】:

我注册帐户只是为了回答您的问题,因为这类问题(以及一些相关问题)的好的答案很少。

您描述的问题主要发生在 chrome、FF 和 IE 中,它们似乎足够聪明,不会在这些情况下在 AJAX 和常规调用之间共享缓存。

问题

让我们首先为未来的读者描述为什么会出现这个问题:

  • 浏览器 (Chrome) 使用常规的 <img><script> 标记询问服务器。如果服务器在同一个域中,则不包含 CORS 标头。
  • 服务器 (S3) 返回资源。如果请求中没有 Origin 标头,则不会在回复中附加 CORS 标头,因为它们是多余的。
  • 浏览器 (Chrome) 尝试使用 AJAX 再次获取资源,但这一次并没有真正进入服务器,而是查看缓存的资源。
  • 浏览器 (Chrome) 缓存版本没有 CORS 标头。它会将请求作为 Access-Control-Allow-Origin 违规或其他相关问题丢弃。

解决办法

在 HTML5 中有一个名为 crossorigin 的属性可以添加到标签中,以表示它们需要发送原始信息。 可能的值是 crossorigin='anonymous'crossorigin='use-credentials' 这些与所提出的问题完全无关,但正如文档中所说:

默认情况下(即不指定属性时),根本不使用CORS。

https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes

所以只需像这样<img src='cloundfront.path' crossorigin='use-credentials'>创建你的图片标签

就是这样。它非常晦涩,所以我希望这个答案可以为一群人节省一些研究时间。

【讨论】:

  • 我认为crossorigin="use-credentials" 等同于在XHR 请求上调用withCredentials 是否正确?如果是这样,就确保返回 CORS 标头而言,crossorigin="anonymous" 是否也能正常工作?如果可以的话,我宁愿不要让我的静态图像做设置 cookie 之类的事情。
  • 这个缓存问题让我在我们的 Chrome 扩展程序中丧命。特别是在带有 CORS 的 Chrome 扩展中,有很多需要考虑的地方。这个答案很清楚,并帮助我们查明了问题。谢谢?。也仅供参考,如果您想避免图像属性crossorigin,您可以使用cache:no-store 执行fetch 请求,这将绕过缓存。
  • 我同意@JeremyT 我认为crossorigin="anonymous" 是静态资产更受欢迎的方法。这就是我在获取启用了 cors 的缓存图像时解决的问题。
【解决方案2】:

另一种解决方案是将您的 CloudFront 分配配置为自动将非 CORS 请求转换为 CORS 请求。这可以通过使用最近添加的 CloudFront 功能“控制边缘到源请求标头”向 CloudFront 发送到 S3 的每个请求添加 CORS 标头来实现。

在此处查看功能公告:https://aws.amazon.com/blogs/aws/cloudfront-update-https-tls-v1-1v1-2-to-the-origin-addmodify-headers/

这里的文档:http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/forward-custom-headers.html

【讨论】:

  • 很好,这将强制 Access-Control-Allow-Origin 但对于 Vary: Origin?
  • 如果您对每个请求强制使用 Access-Control-Allow-Origin,则不再需要“Vary: Origin”,因为请求头不再因请求而异。如果浏览器使用缓存版本不再有问题,因为该版本也启用了 CORS。
  • 但是,如果您强制 CloudFront 始终将“Origin: X.domain.com”发送到 S3,则 CloudFront 无法返回“Access-Control-Allow-Origin: Y.domain” .com”。换句话说,此强制标头解决方案仅在您返回“Access-Control-Allow-Origin: *”通配符响应标头或仅在我们的“访问控制”中返回 single 域时才有效-Allow-Origin" 标题。
  • 我们强制 CloudFront 将 Origin 发送到 S3:phhh。在 s3 上配置的 CORS。 S3 认为来源与主机不同,然后使用 ACA* 标头进行回答。因此,而不是变化 - 每个请求都会获取 cors 标头
【解决方案3】:

我偶然发现了一种让 Cloudfront 始终添加“Vary: Origin”标头的简单方法,尽管据我所知没有记录:您可以通过在 CloudFront 缓存键中包含“Origin”来强制使用“Vary”标头。

在 Cloudfront 发行版上单击“编辑行为”,找到标题“缓存键和源请求”。如果您使用的是“旧版缓存设置”,请单击“添加标题”下的“来源”。如果您使用较新的缓存策略,则需要单击“创建策略”并在“缓存键设置”下添加 Origin,然后返回并使用刚刚创建的策略。

我的用例是 HMTL5 视频字幕轨道,如果您使用 crossorigin="anonymous",则不发送 Origin,如果没有 Origin,则没有 Vary: Origin。

【讨论】:

    猜你喜欢
    • 2020-05-10
    • 2014-10-09
    • 2023-04-11
    • 2015-03-13
    • 2013-12-19
    • 2018-02-20
    • 1970-01-01
    • 2020-07-05
    • 2014-08-16
    相关资源
    最近更新 更多