我从第三方应用程序
获得以下aws s3 api
终点
https://xxx.s3.amazonaws.com/uploads/74d75512c28b49358846f959bd798536?Signature=lxBIZJD7DN4QK3LPmsHxR7D2eTA%3D&Expires=1506108780&AWSAccessKeyId=AKIAJG6Z6A5TUL7ULPXA
我正在尝试将PUT request
这个网址设为upload an File
,但始终获得以下error
#<Net::HTTPForbidden 403 Forbidden readbody=true>
更新以下是回复正文
<?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>AKIAJG6Z6A5TUL7ULPXA</AWSAccessKeyId>
<StringToSign>
PUT
application/xml
1506144576
/xxx/uploads/93a64f8081804604be917b4185c5ed58
</StringToSign>
<SignatureProvided>8pwtC2vtN4LuOwGc887AlT2ZnUc=</SignatureProvided>
<StringToSignBytes>50 55 </StringToSignBytes>
<RequestId>B2B18369BA23A92F</RequestId>
<HostId>YCtjOJsfskITKxjW96ouZq1BV=</HostId>
</Error>
如果我inspect
response
它显示在data
之后,但不明白这有什么问题?没有其他线索,任何人都可以提供帮助将不胜感激。
{
"x-amz-request-id" => [
[0] "385D5CADFE6175FC"
],
"x-amz-id-2" => [
[0] "4uD51Gb/rJy0QooQVmF25Qbp0E568bB9v1P4Grg9CTM2dJ/Iiccad/IyuuEnWDphlGZrr8ZUnQw="
],
"content-type" => [
[0] "application/xml"
],
"transfer-encoding" => [
[0] "chunked"
],
"date" => [
[0] "Fri, 22 Sep 2017 19:28:01 GMT"
],
"server" => [
[0] "AmazonS3"
]
}
我正在运行以下代码段
uri = URI.parse(aws_api_end_point)
request = Net::HTTP::Put.new(uri)
request.body = File.read(file_path)
request.content_type = 'application/xml'
http = Net::HTTP.start(uri.host, uri.port, :use_ssl => true)
response = http.request(request)
注意::我没有使用任何aws SDK。
答案 0 :(得分:1)
请求签名是确定性的 - 对于给定时刻的给定请求,只有一个有效签名。出于所有实际目的,反之亦然 - 对于任何签名,您只能做出一个有效请求。其他任何东西,签名都不匹配。
该算法的设计不是逆向工程,因此我们无法说出他们在给您签名时要求您做出的请求。
但是,我们确实有这个。我相信有些空白丢失了,所以我把它添加回来了:
<StringToSign>
PUT
application/x-www-form-urlencoded
1506144576
/xxx/uploads/93a64f8081804604be917b4185c5ed58
</StringToSign>
这是您提出的请求(不是您应该提出的请求),使用此伪代码转换为canonical form。
StringToSign =
HTTP-VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Expires + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
问题最明显的候选人是Content-Type
。几乎可以肯定,他们不希望您使用application/x-www-form-urlencoded
因为S3 PUT
对象操作不使用HTML表单上传。 S3 PUT
期望请求正文中对象的原始八位字节,以及Content-Type
标头匹配。 S3本身实际上并不验证它们是否匹配(标题与正文),但至少没有预期的 Content-Type
标题,上传将被阻止。
如果您向第三方API提供Content-Type
,那么您的上传需要在S3上传时使用相同的类型,因为签名需要它。
不幸的是,出于故障排除的目的,无法使用预先签名的URL使请求无效的事情无数。来自第三方的文档应阐明他们希望您做出的后续请求的结构。