代码之家  ›  专栏  ›  技术社区  ›  Thayne

S3 CORS,始终发送Vary:Origin

  •  23
  • Thayne  · 技术社区  · 9 年前

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

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

    有没有办法让S3始终返回“Vary:Origin”标头?

    3 回复  |  直到 9 年前
        1
  •  33
  •   drdrek    9 年前

    我做了一个解释,只是为了回答你的问题,因为这类问题(以及一些相关问题)几乎没有好的答案。

    您所描述的问题主要是在chrome、FF和IE中由于某种原因而发生的,在这些情况下,似乎足够聪明,不会在AJAX和常规调用之间共享缓存。

    问题

    让我们先为未来的读者描述问题发生的原因:

    • 浏览器(Chrome)使用常规 <img> <script> 标签如果服务器位于同一域中,则不包含CORS标头。
    • 服务器(S3)返回资源。如果请求中不存在Origin标头,则不会在回复中附加CORS标头,因为它们是冗余的。
    • 浏览器(Chrome)尝试使用AJAX再次获取资源,但这次并没有真正转到服务器,而是查看缓存的资源。
    • 浏览器(Chrome)缓存版本没有CORS标头。它将丢弃请求,因为访问控制允许源代码冲突或其他相关问题。

    解决方案

    在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'>

    就是这样。它相当晦涩,所以我希望这个答案能为很多人节省一些研究时间。

        2
  •  15
  •   Kristian Hanekamp    9 年前

    另一个解决方案是配置您的CloudFront分发版,以自动将非CORS请求转换为CORS请求。这可以通过使用最近添加的CloudFront功能“Control Edge to Origin request Headers”向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 .

        3
  •  1
  •   Jan M    3 年前

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

    在Cloudfront分发版上,单击“编辑行为”,找到标题“缓存密钥和原始请求”。如果您正在使用“传统缓存设置”,请单击“添加标题”下的“原点”。如果使用较新的缓存策略,则需要单击“创建策略”并在“缓存密钥设置”下添加“源”,然后返回并使用刚刚创建的策略。

    我的用例是HMTL5视频字幕曲目,如果您使用 crossorigin="anonymous" ,如果没有起源,就没有瓦里:起源。