php s3预先签名的网址没有sdk

时间:2017-10-21 11:42:40

标签: php amazon-web-services amazon-s3

我正在使用此类生成包含策略部分的直接上载表单。

https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/

上传工作正常,但我希望能够在网站上为用户显示网址中的文件而不公开文件。

我理解SDK有一个简单的方法,但我希望我可以使用现有代码,因为这已经创建了策略。我想知道从头开始创建这个URL的步骤是什么?仅仅为一个函数包含整个膨胀的SDK似乎过分了。

3 个答案:

答案 0 :(得分:1)

我通过使用这两个类来解决它并稍微修改它们来创建一个带有两个函数geturl和getform而不是使用API​​的类,这些对于v4签名非常有用。

getform:

https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/

的getURL:

https://gist.github.com/anthonyeden/4448695ad531016ec12bcdacc9d91cb8

答案 1 :(得分:0)

创建S3预签名URL对于GET请求实际上非常容易。 PUT相当容易,但POST很复杂,需要一个策略。

挑战在于创建签名代码。亚马逊支持两个版本v2和v4。 v2正在逐步淘汰。 v4对代码来说有点复杂。

如果您只是为GET请求创建预签名URL,请编写自己的代码。对于其他任何事情,我认真推荐使用SDK。

下面是使用没有AWS SDK的PHP使用S3V4预签署S3 URL的源代码的链接。

S3LINK-V4.PHP

答案 2 :(得分:0)

我使用@xmxmxmx答案在php中编写了一个函数,对我来说很好用

function AWS_S3_PresignDownload($AWSAccessKeyId, $AWSSecretAccessKey, $BucketName, $AWSRegion, $canonical_uri, $expires = 8400)
{
    $encoded_uri = str_replace('%2F', '/', rawurlencode($canonical_uri));
    // Specify the hostname for the S3 endpoint
    if ($AWSRegion == 'us-east-1') {
        $hostname = trim($BucketName . ".s3.amazonaws.com");
        $header_string = "host:" . $hostname . "\n";
        $signed_headers_string = "host";
    } else {
        $hostname =  trim($BucketName . ".s3-" . $AWSRegion . ".amazonaws.com");
        $header_string = "host:" . $hostname . "\n";
        $signed_headers_string = "host";
    }

    $currentTime = time();
    $date_text = gmdate('Ymd', $currentTime);

    $time_text = $date_text . 'T' . gmdate('His', $currentTime) . 'Z';
    $algorithm = 'AWS4-HMAC-SHA256';
    $scope = $date_text . "/" . $AWSRegion . "/s3/aws4_request";

    $x_amz_params = array(
        'X-Amz-Algorithm' => $algorithm,
        'X-Amz-Credential' => $AWSAccessKeyId . '/' . $scope,
        'X-Amz-Date' => $time_text,
        'X-Amz-SignedHeaders' => $signed_headers_string
    );

    // 'Expires' is the number of seconds until the request becomes invalid
    $x_amz_params['X-Amz-Expires'] = $expires + 30; // 30seocnds are less
    ksort($x_amz_params);

    $query_string = "";
    foreach ($x_amz_params as $key => $value) {
        $query_string .= rawurlencode($key) . '=' . rawurlencode($value) . "&";
    }
    
    $query_string = substr($query_string, 0, -1);

    $canonical_request = "GET\n" . $encoded_uri . "\n" . $query_string . "\n" . $header_string . "\n" . $signed_headers_string . "\nUNSIGNED-PAYLOAD";
    $string_to_sign = $algorithm . "\n" . $time_text . "\n" . $scope . "\n" . hash('sha256', $canonical_request, false);

    $signing_key = hash_hmac('sha256', 'aws4_request', hash_hmac('sha256', 's3', hash_hmac('sha256', $AWSRegion, hash_hmac('sha256', $date_text, 'AWS4' . $AWSSecretAccessKey, true), true), true), true);

    $signature = hash_hmac('sha256', $string_to_sign, $signing_key);
    return 'https://' . $hostname . $encoded_uri . '?' . $query_string . '&X-Amz-Signature=' . $signature;
}

使用

调用
echo AWS_S3_PresignDownload('accessId', 'seceret', 's3BucketName', 'reGion', '/fileKey.ext', 60);