通过 CloudFront 上传到 S3 结果为 403

Upload to S3 via CloudFront results in 403

我正在尝试签署 URL 以通过 CloudFront 上传到 S3。

如果我签署 URL 政策:

https://staging.*SNIP*.io/341-a25e82ef-8210-49bc-9fbd-b3f0c4807080-original.jpg?Policy=*SNIP*&Signature=*SNIP*&Key-Pair-Id=*SNIP*

或者没有政策但使用过期

https://staging.*SNIP*.io/343-aa3e9a57-4d85-4c90-bf05-3d6fdac04a49-original.jpg?Expires=1457765627&Signature=*SNIP*&Key-Pair-Id=*SNIP*

我的一致性得到:

<Error>
    <Code>AccessDenied</Code>
    <Message>Query-string authentication requires the Signature, Expires and AWSAccessKeyId parameters</Message>
    <RequestId>*snip*</RequestId>
    <HostId>*snip*</HostId>
</Error>

我根据各种不同的 SO 答案推出了自己的签名。我试过使用 AWS SDK 的内置签名。我已经销毁并重新创建了 CloudFront 发行版。

我完全 运行 没有想法可以尝试。

我可能已经查看了 SO 上关于使用 cloudfront 签名 url 的每一个问题,但没有任何帮助。我无法克服这个 403 错误。

编辑: 似乎 AWS 不知道为什么它不工作,它似乎都配置正确。

我设法解决了这个问题。文档(在撰写本文时)让我感到困惑。基本上:

1) 需要设置 Cloudfront Distribution 来限制对 bucket 的访问。 (如果不这样做,它似乎不会将身份验证 headers 传递给 S3)

2) 哈希负载

3) 签署 Cloudfront URL

4) 签署请求

我使用 Crypto.js(核心和 SHA256)

对有效负载进行哈希处理
var reader = new FileReader();

reader.onload = function(readerEvt) {
    var binaryString = readerEvt.target.result;
    var wordArray = arrayBufferToWordArray(binaryString);
    var hash = CryptoJS.SHA256(wordArray);

    var hashedPayload = hash.toString(CryptoJS.enc.Hex);

    // send the hashed payload serverside for use in calculating the signed request
};

reader.readAsArrayBuffer(file);

并签署我遵循的请求:

http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html

(如果您需要更多信息,请发表评论)