尝试从JSP中将对象PUT到REST API时的SignatureDoesNotMatch - AWS V4签名

时间:2016-09-22 17:58:56

标签: java rest jsp amazon-web-services amazon-s3

我按照以下步骤使用V4创建PUT请求:http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html

刚刚创建了一个JSP,用于尝试将文件上传到S3存储桶。问题是我总是得到403 - 禁止。通过详细查看回复,它说的是 SignatureDoesNotMatch '错误,消息是' 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。' 内容实际上只是字符串'文件内容'。这些是发送的标题:

PUT /test.txt HTTP/1.1
Accept: /
Host: my host.s3.amazonaws.com
Date: Thu, 22 Sep 2016 04:51:52 GMT
Authorization: AWS4-HMAC-SHA256 Credential=My access ID/20160922/us-east-1/s3/aws4_request,SignedHeaders=date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class,Signature=1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs=
x-amz-date: 20160922T045152Z
x-amz-content-sha256: 69423BABE8E61AAB549F347BCC8B9D77B7DCACA198FB0597BDE0B5F97F968E38
x-amz-storage-class: REDUCED_REDUNDANCY
Content-Type: text/plain
Content-Length: 13

响应机构的重要部分是:

<CanonicalRequest>PUT
/test.txt

content-length:13
content-type:text/plain
date:Thu, 22 Sep 2016 04:51:52 GMT
host:my host.s3.amazonaws.com
x-amz-content-sha256:69423BABE8E61AAB549F347BCC8B9D77B7DCACA198FB0597BDE0B5F97F968E38
x-amz-date:20160922T045152Z
x-amz-storage-class:REDUCED_REDUNDANCY

content-length;content-type;date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class
69423BABE8E61AAB549F347BCC8B9D77B7DCACA198FB0597BDE0B5F97F968E38</CanonicalRequest>

<StringToSign>AWS4-HMAC-SHA256
20160922T045152Z
20160922/us-east-1/s3/aws4_request
17957a94c148833cd2f1132a8a4ffcfe6d2c83a71501a063f7a2ff9e7acfa1aa</StringToSign>

<SignatureProvided>1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs</SignatureProvided>

我很确定CanonicalRequest和StringToSing在我得到的响应和我创建的请求上是相同的,因为我们现在正在记录所有这些信息以进行调试。通过比较,我可以确保数据完全相同,除了&#39; =&#39;签名末尾的字符:

授权标题签名:

1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs=

签名提供给响应机构:

1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs

我只是想不通为什么我得到这个SignatureDoesNotMatch错误,似乎一切都好了(除了这个&#39; =&#39;字符,我不知道为什么不包括在签名提供回复)。我附上了我用来创建请求的代码。

我有什么遗失的东西吗?这是我第一次尝试与AWS集成。我已经花了很多天试图让它发挥作用,这很烦人:(

提前感谢您的帮助!

编辑:删除最后一个&#39; =&#39;签名中的字符没有起作用,结果与上面相同。

1 个答案:

答案 0 :(得分:0)

一个快速的谷歌搜索告诉我额外的“=”实际上是通过填充因子添加的,甚至更快的测试用例帮助我找到了一种没有填充的编码方式。

@Test
public void testSign(){
    byte[] b = Base64.getDecoder().decode("1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs=");
    System.out.println(Base64.getEncoder().withoutPadding().encodeToString(b));
}

并不令人惊讶,如果我删除withoutPadding(),我得到=最后,也许你可以使用java.net.Base64进行编码而不用填充。