Aws s3签名与- presigned url不匹配


aws s3 signature does not match -pre signed url

我想通过预先签名的url上传文件到aws s3。我使用这个github项目https://github.com/JoernBerkefeld/s3SignedUpload,但它显示错误,而上传。

<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>AKIAI2DLTCOXU5255TMQ</AWSAccessKeyId>
<StringToSign>
AWS4-HMAC-SHA256 20160810T174345Z 20160810/ap-south-1/s3/aws4_request a63f9ead869c1fb4d06fa1169458b87978d86fd44348144636c2e0cb2c10cdf5
</StringToSign>
<SignatureProvided>
ae7bd98265316de85f3c55e539ca9bdb5934620428a7924b9404a9403dd9d4d2
</SignatureProvided>
<StringToSignBytes>
41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 31 36 30 38 31 30 54 31 37 34 33 34 35 5a 0a 32 30 31 36 30 38 31 30 2f 61 70 2d 73 6f 75 74 68 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 61 36 33 66 39 65 61 64 38 36 39 63 31 66 62 34 64 30 36 66 61 31 31 36 39 34 35 38 62 38 37 39 37 38 64 38 36 66 64 34 34 33 34 38 31 34 34 36 33 36 63 32 65 30 63 62 32 63 31 30 63 64 66 35
</StringToSignBytes>
<CanonicalRequest>
GET /logo.jpg Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAI2DLTCOXU5255TMQ%2F20160810%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20160810T174345Z&X-Amz-Expires=1800&X-Amz-SignedHeaders=Host host:indiastreetz.s3.ap-south-1.amazonaws.com host UNSIGNED-PAYLOAD
</CanonicalRequest>
<CanonicalRequestBytes>
47 45 54 0a 2f 6c 6f 67 6f 2e 6a 70 67 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3d 69 6d 61 67 65 25 32 46 6a 70 65 67 26 58 2d 41 6d 7a 2d 41 6c 67 6f 72 69 74 68 6d 3d 41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 26 58 2d 41 6d 7a 2d 43 72 65 64 65 6e 74 69 61 6c 3d 41 4b 49 41 49 32 44 4c 54 43 4f 58 55 35 32 35 35 54 4d 51 25 32 46 32 30 31 36 30 38 31 30 25 32 46 61 70 2d 73 6f 75 74 68 2d 31 25 32 46 73 33 25 32 46 61 77 73 34 5f 72 65 71 75 65 73 74 26 58 2d 41 6d 7a 2d 44 61 74 65 3d 32 30 31 36 30 38 31 30 54 31 37 34 33 34 35 5a 26 58 2d 41 6d 7a 2d 45 78 70 69 72 65 73 3d 31 38 30 30 26 58 2d 41 6d 7a 2d 53 69 67 6e 65 64 48 65 61 64 65 72 73 3d 48 6f 73 74 0a 68 6f 73 74 3a 69 6e 64 69 61 73 74 72 65 65 74 7a 2e 73 33 2e 61 70 2d 73 6f 75 74 68 2d 31 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 0a 68 6f 73 74 0a 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44
</CanonicalRequestBytes>
<RequestId>78A21E02C733E895</RequestId>
<HostId>
rBd5ZQBuMyjouFZbSavDcFX4n4fEuqSj8aZuCQyw9rChSSpZkBFZjd8CXqog2OWPMX96OSIuFmo=
</HostId>
</Error>

答案我发现在stackoverflow不修复我的解决方案。请告诉我如何修复或在哪里找到错误。

public function getSignedUrl($filename, $mime) {   
        if(!$filename) {   
            return $this->error('filename missing');   
        }    
        if(!$mime) {     
            return $this->error('mime-type missing');    
        }     
        $final_filename = $this->get_file_name($filename);        
        try {     
            $signedUrl = $this->client->getCommand('PutObject', array(    
                'Bucket' => $this->bucket,    
                'Key' => $this->folder.$final_filename,    
                'ContentType' => $mime,    
                'Body'        => '',     
                'ContentMD5'  => false     
            ))->createPresignedUrl('+30 minutes');    
        } catch (S3Exception $e) {      
            echo $e->getMessage() . "'n";    
        }     
        $signedUrl .= '&Content-Type='.urlencode($mime);
        return array('url'=>$signedUrl);
    }

我使用PHP内置的散列函数对上传进行预签名,然后使用POST上传文件。

当用户点击上传按钮时,它将从presign_url获得预签名的数据,然后开始上传到aws。

 $.ajax({
                url: 'presign_url.php',
                type: 'post',
                dataType: 'json',
                success: function (data) {
                   send_img(png,image_size,data); /* append this data with your post data. I pass the data to my image uploading function.data contains presigned data(image name,file size,format and other amazon credentials )*/
                },
                data: {}
            });
//presign_url.php

 <?php
    $access_key         = "XXXXXXXXXXXX"; //Access Key
    $secret_key         = "xyzxyzxyzxyz"; //Secret Key
    $my_bucket          = "bucketname"; //bucket name
    $region             = "your region"; //bucket region ex:-ap-south-1
    $success_redirect   = "http://localhost/info";// your redirect url
    $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; //URL to which the client is redirected upon success (currently self) 
    $allowd_file_size   = "1048579"; //1 MB allowed Size
    //dates
    $short_date         = gmdate('Ymd'); //short date
    $iso_date           = gmdate("Ymd'THis'Z"); //iso format date
    $expiration_date    = gmdate('Y-m-d'TG:i:s'Z', strtotime('+1 hours')); //policy expiration 1 hour from now
    $filename=uniqid().".jpg"; // file name to be which file is saved.
    //POST Policy required in order to control what is allowed in the request
    //For more info http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
    $policy = utf8_encode(json_encode(array(
                        'expiration' => $expiration_date,  
                        'conditions' => array(
                            array('acl' => 'public-read'),  
                            array('bucket' => $my_bucket), 
                            array('success_action_redirect' => $success_redirect),
                            array('starts-with', '$key','user/'),
                            array('content-length-range', '1', $allowd_file_size), 
                            array('x-amz-credential' => $access_key.'/'.$short_date.'/'.$region.'/s3/aws4_request'),
                            array('x-amz-algorithm' => 'AWS4-HMAC-SHA256'),
                            array('X-amz-date' => $iso_date)
                            )))); 
    //Signature calculation (AWS Signature Version 4)   
    //For more info http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html  
    $kDate = hash_hmac('sha256', $short_date, 'AWS4' . $secret_key, true);
    $kRegion = hash_hmac('sha256', $region, $kDate, true);
    $kService = hash_hmac('sha256', "s3", $kRegion, true);
    $kSigning = hash_hmac('sha256', "aws4_request", $kService, true);
    $signature = hash_hmac('sha256', base64_encode($policy), $kSigning);
    $arr=array();
    $arr["u"]="http://$my_bucket.s3.amazonaws.com/";
    $arr["k"]=$filename;
    $arr["a"]="public-read";
    $arr["ac"]="$access_key/$short_date/$region/s3/aws4_request";
    $arr["aa"]="AWS4-HMAC-SHA256";
    $arr["ad"]=$iso_date;
    $arr["p"]=base64_encode($policy);
    $arr["as"]="$signature";
    $arr["sar"]="$success_redirect";
    $arr["us"]="user/";
    echo json_encode($arr);
    ?>