Ajax AWS S3不发送访问控制允许原始报头(当存在请求原始报头时)

Ajax AWS S3不发送访问控制允许原始报头(当存在请求原始报头时),ajax,amazon-web-services,amazon-s3,cors,Ajax,Amazon Web Services,Amazon S3,Cors,我有一个AWS S3存储桶,具有以下CORS策略: <?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GE

我有一个AWS S3存储桶,具有以下CORS策略:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
        <ExposeHeader>Access-Control-Allow-Origin</ExposeHeader>
    </CORSRule>
</CORSConfiguration>


我创建了一个测试桶,启用了CORS,并使用了您的CORS规则

请注意,我不相信
访问控制允许源代码
是必要的,但它的存在不应该造成任何伤害,所以我保留了它

我在测试中观察到的行为与您在浏览器的请求/响应头中显示的行为不一致

使用curl,我将
Origin:
标题设置为
http://example.com
。(是的,这实际上是我设置的…在下面的输出中没有修改)

$curl-vhttp://xxxxxxxxxxxx.s3.amazonaws.com/index.txt -H'来源:http://example.com'
*在DNS缓存中找不到主机名
*正在尝试54.231.98.120。。。
*已连接到xxxxxxxxxxx.s3.amazonaws.com(54.231.98.120)端口80(#0)
>GET/index.txt HTTP/1.1
>用户代理:curl/7.35.0
>主持人:XXXXXXXXXX
>接受:*/*
>来源:http://example.com
>
为什么这很有趣

S3,在配置CORS且
与您的请求相匹配的情况下,始终返回CORS响应头a
Vary:
头(这意味着“如果您更改请求中的以下头之一,我可能会更改我的响应。”)我所指的上述输出中的头,具体来说,就是这些

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Expose-Headers: Access-Control-Allow-Origin
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
我只能找到一个例外,那就是没有匹配的CORS规则。为了证明这一点,我首先将CORS配置更改为
http://example.com
,然后重复该请求。请注意,响应几乎相同,只是S3在响应中使用了确切的原点,并添加了
访问控制允许凭据

< Access-Control-Allow-Origin: http://example.com
< Access-Control-Allow-Methods: GET
< Access-Control-Expose-Headers: Access-Control-Allow-Origin
< Access-Control-Allow-Credentials: true
< Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
这让我回到了我最初的结论,即您显示的浏览器发出的请求与您为CORS配置bucket的时间不匹配,并且可能在bucket的CORS设置处于正确状态之前,或者在它们与您在问题中发布的设置匹配之前被缓存

如果该请求上存在
Origin:
头,正如浏览器显示的那样,那么S3应该添加CORS响应头,不管该请求是否实际是跨源请求


接下来的步骤是在新路径上使用一个不可能被缓存的新对象尝试此操作,或者尝试在请求时向对象的URL添加
?some random=thing
的常见浏览器缓存破坏策略。如果不这样做,你应该考虑使用一个工具(如代码> Curl < /Cord>)来证明或反驳你的正确行为,它准确地显示了请求/响应中发生的事情。

很明显,这是在你的缓存中,并且看起来已经被原始请求中的原点头集缓存了…所以,第一个问题是,它在您在bucket上配置CORS之前到达了吗?这在生产中是可能的,但我强调要经常清除缓存,所以我认为缓存中的映像应该在设置CORS策略之后被请求。但是,每个图像有两个请求,所以我不确定这是否有区别。第一个请求是浏览器发送的标准http get请求。第二个是SDK发送的ajax请求,我用一些新的图像做了更多的测试,以确保不存在预先缓存的可能性。我发现(至少在Safari中),网络选项卡告诉我第二个请求是从缓存中提供的。因此,尽管它有正确的标题,但不知何故,浏览器提供的缓存版本没有
Origin
标题。我决定尝试你的方法,在url中添加一个随机的查询参数,但到目前为止,它似乎仍然有效。将bucket CORS配置更改为
http://example.com
(使用您的实际域)。如果您有多个(同一主机的https与http的来源不同),则为每个来源创建相同的
块。Safari可能会在没有告诉你的情况下用通配符打电话给BS。没有骰子。我试过那种方法。我创建了一个具有特定来源和通配符来源的策略,但失败了。也只尝试了特定的来源(没有通配符规则),但仍然失败。我很确定这是一个缓存问题。你建议的那个破坏缓存的把戏似乎是唯一对我有用的东西,我相信你一直都是对的。。。您的问题可能确实是缓存问题,这是S3方面有问题的行为。在非CORS响应中,它应该返回
Vary:Origin
,但它不返回。有关此问题的分析和解决方法,请参阅Lambda@Edge.Interesting找到那里!如果我没记错的话,我只是在每个文件名(例如utm=1234556789)的末尾添加了一个带有unix时间戳的查询字符串,以强制浏览器再次请求该文件。
< HTTP/1.1 200 OK
< x-amz-id-2: WJ0QmIZ6jTQYefFi8GjlDQkZKFHDX8/5cmejeulhG1ov3/NdoSXbsTKetYpxvXPML8aUnPNZ/ac=
< x-amz-request-id: 15A03D8B1E08A830
< Date: Sat, 28 May 2016 21:58:34 GMT
< Cache-Control: no-cache
...etc.