使用AWS SDK for PHP v2为文件上载创建预先签名的POST URL

时间:2016-05-30 14:32:51

标签: php amazon-s3 aws-sdk

我尝试在相当旧的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是在文件上传之前生成的,我不确定如何获得该信息。

如果有人能够看到任何明显错误导致此失败的事情,我们将非常感谢任何建议。

1 个答案:

答案 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的文档中根本没有看到这一点。