我尝试在相当旧的Web服务器上设置上传过程,以便当用户向其上传新文件时,客户端首先向Web服务器发送请求(不包含该文件),做一些处理并返回一个预先签名的URL,允许客户端将文件直接上传到S3。
应该注意的是,由于服务器上安装了PHP版本,我使用的是AWS SDK for PHP的v2。
我可以使用以下代码创建预签名网址:
$s3Client = Aws\S3\S3Client::factory(array(
'key' => "xxxxxxxxxxxxxxxxxxxx",
'secret' => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
));
$command = $s3Client->getCommand('PutObject', array(
'Bucket' => 'bucketname',
'Key' => $this->_id.'/model.xyz',
'Body' => '',
'ContentMD5' => false,
'ContentType' => 'multipart/form-data',
));
return $command->createPresignedUrl('+20 minutes');
这会成功创建一个传递给客户端的URL。但是,在将后续请求发送到S3时,我收到此错误:
<?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>xxxxxxxxxxxxxxxxxxxxxxx</AWSAccessKeyId>
<StringToSign>POST
multipart/form-data; boundary=----WebKitFormBoundaryLFAYOUC0JsblZJHj
1464614702
/bucketname/blah/model.xyz</StringToSign>
<SignatureProvided>xxxxxxxxxxxxxxxxxxxxxxxxxxx</SignatureProvided>
<StringToSignBytes>xx xx xx xx xx xx xx xx xx xx xx...</StringToSignBytes>
<RequestId>XXXXXXXXXXXXXXXXXXXX</RequestId>
<HostId>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId>
</Error>
我刚刚创建了使用的访问密钥和密钥(具有足够权限的用户),因此不正确的密钥不是问题。
请求标题:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:50145
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryLFAYOUC0JsblZJHj
Host:bucketname.s3.amazonaws.com
Origin:http://website.com
Pragma:no-cache
Referer:http://website.com/script.php
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
此处显示的内容长度不同,但这很重要吗?鉴于URL是在文件上传之前生成的,我不确定如何获得该信息。
如果有人能够看到任何明显错误导致此失败的事情,我们将非常感谢任何建议。
答案 0 :(得分:0)
您无法使用预先签名的PUT
网址进行POST
上传。
您使用签名的策略文档(描述上传的允许属性的base64编码的JSON),签名以及一些其他属性,例如实际文件的内容类型,所有这些都嵌入在表单中。
对于签名版本2,策略,签名和表单的构造在http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html中描述。
对于签名版本4,相同的信息位于http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html。
请注意&#34;签名版本&#34;与SDK版本无关。所有地区都支持Sig V4。 2014年之前推出的地区也支持Sig V2,从头开始实施起来更容易一些。
我提到这一点,因为我在PHP V2 SDK的文档中根本没有看到这一点。