0

我正在编写用于从 AWS S3 下载对象的预签名 URL。我使用 AWS Java SDK 中的 generatePresignedUrl 方法。但是,在使用生成的预签名 URL 发出 GET 请求时,我从 AWS 获得 SignatureDoesNotMatch。我很困惑,因为我使用官方 SDK 中的方法来生成它和一个非常简单的 GET 请求,但没有运气。非常感谢任何帮助!

代码(取自AWS 文档):

java.util.Date expiration = new java.util.Date();
long milliSeconds = expiration.getTime();
milliSeconds += 1000 * 60 * 60; // Add 1 hour.
expiration.setTime(milliSeconds);

GeneratePresignedUrlRequest generatePresignedUrlRequest = 
new GeneratePresignedUrlRequest(bucketName, objectKey);
generatePresignedUrlRequest.setMethod(HttpMethod.GET); 
generatePresignedUrlRequest.setExpiration(expiration);

URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest); 

我用于连接 AWS S3 的凭据经过测试;我能够使用来自 AWS SDK 的相同凭证和 S3 下载方法下载 S3 对象。但是我从 AWS 获得的对组合 URL 的响应(例如,https://ozland.s3.amazonaws.com/1865b563cdc94fa28ef41ee0b9b0e608?AWSAccessKeyId= ...AWSAccessKeyId...&Expires=1471300223&Signature=pbgcRB0Zg%2B3iicDQQbVX%2FqdNAAc%3D )从上面是:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message
<AWSAccessKeyId>...AWSAccessKeyId...</AWSAccessKeyId>
<StringToSign>GET


1471300223
/ozland/1865b563cdc94fa28ef41ee0b9b0e608</StringToSign>
<SignatureProvided>pbgcRB0Zg+3iicDQQbVX/qdNAAc=</SignatureProvided>
<StringToSignBytes>47 45 54 0a 0a 0a 31 34 37 31 33 30 30 32 32 33 0a 2f 61 6c 61 62 61 6d 61 63 6f 75 6e 74 79 2f 31 38 36 35 62 35 36 33 63 64 65 39 34 66 61 32 38 65 66 34 31 65 65 30 63 39 62 30 65 36 30 38</StringToSignBytes>
<RequestId>...RequestId...</RequestId>
<HostId>...HostId...</HostId></Error>

问题是为什么上面的 response.StringToSign 与 AWS docs ( AWS docs )描述它的方式不同。特别是,根据文档,我希望 StringToSign 像:

AWS4-HMAC-SHA256
20150830T123600Z
20150830/us-east-1/iam/aws4_request
f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59

aws-tools非常适合我使用完全相同的 S3 存储桶和凭据生成预签名 URL。但是为什么我还是在这里得到 SignatureDoesNotMatch 呢?

谢谢!

4

1 回答 1

2

不同之处在于,错误响应中的签名字符串是Signature Version 2格式,而这又是因为您的签名 URL 是 V2 格式。

在两种格式之间的显着视觉差异中,V2 有Signature=[base64],而 V4 有X-Amz-Signature=[hex].

这解释了要签名的字符串的区别。

它不会让您更接近解释签名不匹配的原因,因为 V2 在 2014 年之前推出的地区完全有效。

最可能的罪魁祸首通常是密钥中缺少字符或复制/粘贴错误,或者您用来发出请求的任何用户代理正在做一些有趣的事情。如果要签名的字符串与您正在发出的请求匹配 - 看起来确实如此 - 如果您的密钥是使用不需要 urlencoding 的 ASCII 子集中的字符命名的,那么在 V2 中就不会出错 - - 就像这个请求一样。(键中的有效字符是 UTF-8,但 ASCII 字母数字字符可以很好地被所有用户代理普遍还原)。

于 2016-08-15T23:47:00.287 回答