AWS 预签名 URL

Posted

技术标签:

【中文标题】AWS 预签名 URL【英文标题】:AWS Pre signed URL 【发布时间】:2018-02-01 22:04:44 【问题描述】:

我正在尝试使用 php/javascript 将图像/视频上传到 AWS S3

这是我的 PHP 代码

<?php
use Aws\S3\Exception\S3Exception;


    $filename = isset($_GET['file']) ? $_GET['file'] : '';
    $mime = isset($_GET['mime']) ? $_GET['mime'] : '';

    function getSignedUrl($filename, $mime) 


        require $_SERVER['DOCUMENT_ROOT'].'/ibrainmart/start.php';

        $BUCKET = $config['S3']['bucket'];
        $tmp_name = $filename;



        try 
            $command= $S3->getCommand('PutObject', array(
                    'Bucket'      => $BUCKET,
                    'Key'         => $tmp_name,
                    'ContentType' => $mime,
                    'Body'        => ''

            ));
            $signedUrl = $S3->createPresignedRequest($command, "1 week");
         catch (S3Exception $e) 
            echo $e->getMessage() . "\n";
        
        echo $signedUrl->getUri();
        return $signedUrl->getUri();
    


    echo getSignedUrl($filename,$mime);

?>

这是我的 Java 脚本代码

$(function()
    // run onLoad

    $("#profilePic").uploadHandler("headerupload.php");
);

// Upload image to S3
$.fn.uploadHandler = function(s3presignedApiUri) 

    $(document).ready(function (e) 
        $("#profilePic").on('change',(function(e) 
        e.preventDefault();

        console.log("ajax going to start..!");
        var fileupload = $('input[name=file]');
        var fileToUpload = fileupload[0].files[0];
           if(fileToUpload !="undefined")
            var formData = new FormData();
            formData.append("file", fileToUpload);
           
        console.log("fileToUpload.name"+fileToUpload.name);
        $.ajax(
                url: s3presignedApiUri, // Url to which the request is send
                type: "GET",             // Type of request to be send, called as method

                data: 'file='+ fileToUpload.name + '&mime=' + fileToUpload.type , // Data sent to server, a set of key/value pairs (i.e. form fields and values)


                cache: false,             // To unable request pages to be cached
                )       


                .done(function(data)   // A function to be called if request succeeds
                

                    console.log("data ............"+data);

                    $.ajax(
                        url : data.url,
                        type : "PUT",
                        data : fileToUpload,
                        cache : false,
                        contentType : fileToUpload.type,
                        processData : false
                    )
                    .done(function() 

                        console.info("s3-upload done: "); // REMOVE ME FOR PRODUCTION USE

                    )
                    .fail(function(e) 
                        console.error("s3-upload failed",e); // REMOVE ME FOR PRODUCTION USE
                    );
                )
                .fail(function(e)
                        
                        console.log("file passing error.!");
                    )

                ));

    );



所有这些功能都很好,我想即使在执行之后它也会给我文件上传成功消息。但是当我检查 s3 时什么都没有。

即使在控制台中,它也会生成 Presignrd URL,如下所示。但是当我尝试单击它时,它会给我 SignatureDoesNotMatch 错误。(请单击 URL)。可能是什么错误..?

https://ibrainmartstorage.s3.us-east-2.amazonaws.com/DSC_1595.JPG?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJZBWQOXKKPC7UXDQ%2F20170824%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20170824T062933Z&X-Amz-SignedHeaders=host&X-Amz-Expires=604800&X-Amz-Signature=a4384c737f191c6a516611f67a322ebf98b8e9e0aff65bbcd84e74c87637fb3dhttps://ibrainmartstorage.s3.us-east-2.amazonaws.com/DSC_1595.JPG?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJZBWQOXKKPC7UXDQ%2F20170824%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20170824T062933Z&X-Amz-SignedHeaders=host&X-Amz-Expires=604800&X-Amz-Signature=a4384c737f191c6a516611f67a322ebf98b8e9e0aff65bbcd84e74c87637fb3d

【问题讨论】:

参考以下文档docs.aws.amazon.com/aws-sdk-php/v3/guide/service/…并检查它是否工作? 【参考方案1】:

经过几天的尝试,找到了这个解决方案。

使用 AWS Cognito Federate 池生成与 AWS S3 的会话并使用临时生成的密钥、accessID 和 Session 上传文件。下面我列出了代码示例。

getAuthenticateUser().getSession(function(err,session)
     if (err) 
        console.log("Error"+err);
        return;
    
    if(session.isValid())
    

        const authenticator = 'cognito-idp.us-east-2.amazonaws.com/us-east-2_cfmOv3jSL';
        AWS.config.region = 'us-east-2'; // Region
        AWS.config.credentials = new AWS.CognitoIdentityCredentials(
        IdentityPoolId: 'us-east-2:XXXXX-d2b7-XXXX-85c7-929aadf450b2',
        Logins: 
            [authenticator]: session.getIdToken().getJwtToken()
          

    );
     AWS.config.credentials.refresh((error) => 
         if (error) 
             console.error(error);
          else 
             console.log('Successfully logged!');
         
    );


    AWS.config.getCredentials(function(err) 
      if (err) console.log(err.stack); // credentials not loaded
      else  
        console.log("Access Key:", AWS.config.credentials.accessKeyId);
      console.log("Access Key:", AWS.config.credentials.secretAccessKey);
     console.log("Access Key:", AWS.config.credentials);

    AWS.config.update(
        AccessKeyId : AWS.config.credentials.AccessKeyId,
        SecretAccessKey : AWS.config.credentials.SecretAccessKey ,
        SessionToken : AWS.config.credentials.SessionToken

    );
      

    );
    

    if(!session.isValid())
    
        console.log("Session is not valid..!");
         //Please Login to Continue
    

    );

【讨论】:

以上是关于AWS 预签名 URL的主要内容,如果未能解决你的问题,请参考以下文章

AWS S3 存储桶预签名 URL

使用其预签名 URL 从 AWS s3 读取文件的内容

AWS S3 通过预签名 URL 上传返回 400 错误请求

Sketch JS,如何在音频标签上使用 AWS 预签名 URL?

AWS S3 PHP SDK 预签名 url 限制内容类型

AWS S3 PHP SDK 预签名 url 限制内容类型