'php s3 pre signed url without sdk
I'm using this class to generate a direct upload form which includes the policy part.
https://designedbyaturtle.com/direct-upload-to-s3-using-aws-signature-v4-php/
The uploads are working but I want to be able to display the file from the url for users on the site without making the files public.
I understand the SDK has a simple method for this but I am hoping I can do it with the existing code as this already creates the policy. I'm wondering what are hte steps for creating this url from scratch? It seems excessive to include the entire bloated SDK for just one function.
Solution 1:[1]
I solved it by using these two classes and modifying them a bit to make a class with two functions geturl and getform instead of using the API, these work great for v4 signatures.
getform:
https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/
geturl:
https://gist.github.com/anthonyeden/4448695ad531016ec12bcdacc9d91cb8
Solution 2:[2]
I wrote a function in php using @xmxmxmx answer and it is working fine with me
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;
}
Call it using
echo AWS_S3_PresignDownload('accessId', 'seceret', 's3BucketName', 'reGion', '/fileKey.ext', 60);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | xmxmxmx |
| Solution 2 |
