1

我正在尝试使用带有 PUT 方法的预签名 URL 将文件从浏览器(Chrome 版本 41.0)上传到 S3。我在我的服务器上正确生成了预签名的 URL,因为它可以从 CURL 正常工作:

curl -X PUT "Content-Type:" --data "junk" "https://mypresignedurl"

我现在正在尝试使用 jQuery 从浏览器上传:

$.ajax({ url: "https://mypresignedurl", method: 'PUT', // I've also tried type: 'PUT' data: "junk", })

这被 AWS 使用 SignatureDoesNotMatch 代码拒绝。错误指定:

<StringToSign>GET 1427216999 /mybucket/myfile</StringToSign>

但我没有使用 GET - 我使用的是 PUT。如果我检查 Chrome 的网络选项卡,它会正确地将请求列为 PUT。那么为什么 AWS 将浏览器 PUT 请求解释为 GET 并拒绝它们呢?

(这似乎与 CORS 无关。我已经在我的存储桶上设置了 CORS,然后使用 -H "Origin: http://elsewhere.com " 从 CURL 进行测试。我也尝试过传递 "type" “方法”。我尝试过使用 POST 而不是 PUT——即使如此,AWS 仍然将 StringToSign 列为 GET。我尝试了各种 contentTypes。FWIW,我的 presignedURL 上传逻辑在 WPF 应用程序中的 .NET 上都可以正常工作。 )

4

1 回答 1

2

好的,让它工作。我现在可以使用预签名 URL 从浏览器上传。

让我失望的是 S3 将我的 PUT 解释为 GET 的问题。但这实际上是错误的。为了找出权限问题,我查看了 Chrome 的网络选项卡。在向 S3 发出 PUT 请求之前,有一个对同一个 S3 端点的 OPTIONS 请求。我单击此以获取更多信息,那时我看到SignatureDoesNotMatch消息<StringToSign>GET ... </StringToSign> 但单击浏览器中的此链接导致浏览器尝试从 S3 获取资源。这不是你应该用它做的。正在使用 OPTIONS 方法检索请求。您可以手动执行此操作curl -X OPTIONS ...如果你真的想要,然后它会正确列出如何访问这个 url。但是不要在浏览器中单击它,否则浏览器会尝试获取它,从而产生与您的原始 PUT 请求无关的废话消息。

那么,为什么我一开始上传时会出错?事实证明我是content-type空白的。浏览器显然不喜欢这个并将其转换为" , text/plain ...". 另一方面, curl 和 .net 似乎可以使用空白content-type,因此它们的行为存在差异。当我content-type = "text/plain"在服务器上生成预签名 URL 和 ajax 上传时都使用相同的方法,一切正常。

于 2015-03-25T00:07:02.933 回答