S3:自定义标头返回403

时间:2016-06-29 21:57:32

标签: amazon-web-services amazon-s3

我有一个将文档上传到S3存储桶的应用。没有问题,但当我在请求中指定一些自定义标题时,如下所示:

req.setHeader('x-amz-meta-purpose', 'purpose');

为存储桶编写匹配的CORS规则:

<CORSRule>
   <AllowedOrigin>http://www.example.com</AllowedOrigin>
   <AllowedMethod>PUT</AllowedMethod>
   <AllowedMethod>POST</AllowedMethod>
   <AllowedMethod>DELETE</AllowedMethod>
   <AllowedHeader>*</AllowedHeader>
   <MaxAgeSeconds>3000</MaxAgeSec>
   <ExposeHeader>x-amz-meta-purpose</ExposeHeader>
</CORSRule>

我收到403回复。我忘记了什么?我的代码工作正常,没有添加自定义标头。

更新

我收到了这个回复:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

如何更改签名以包含自定义标题?它目前是这样的:

String stringToSign = 'PUT\n\n' + contentType + '\n' + now + '\n' + '/' + bucketname + '/' + lead.Id + '/' + fileName;
String encodedStringToSign = EncodingUtil.urlEncode(stringToSign, 'UTF-8');
Blob mac = Crypto.generateMac('HMACSHA1', Blob.valueOf(stringToSign), Blob.valueOf(secret));
String signed = EncodingUtil.base64Encode(mac);

有关如何向其添加标题的任何想法或文档?

1 个答案:

答案 0 :(得分:1)

您正在使用Signature V2,因此您需要包含“Canonicalized Amz Headers”...

String stringToSign = 'PUT\n\n' + 
                      contentType + '\n' + 
                      now + '\n' + 
>>>>>> here >>>>>>    CanonicalizedAmzHeaders +
                      '/' + bucketname + '/' + lead.Id + '/' + fileName;

请注意,此新值后不需要额外的'\ n',但CanonicalizedAmzHeaders字符串本身以'\ n'结尾。

Canonicalized Amz标头是通过迭代每个以x-amz-开头的标头构建的,标头名称转换为小写,然后以词汇方式排序,构建一个看起来像这样的字符串(伪代码):

lowercase(header1) + ':' + trim(value1) + '\n' +
lowercase(header2) + ':' + trim(value2) + '\n' +
...

所以,在你的请求中,最后三行看起来像这样:

[date]\n
x-amz-meta-purpose:purpose\n
/bucketname/key

http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheCanonicalizedResourceElement