1

My needs are simple... One would think. I'm just trying to create a signed URL with a PHP script to prevent download abuse of a file hosted on Google Cloud Storage. I've found several examples, none that worked. This one came the closest:

<?php

$filepath = 'my file.zip'; // do not include the bucket name, no slash in the beginning
$bucket = 'mybucket';
$key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // key
$secret = 'xxxxxxxxxxxxxxxxxxxxxxx'; // secret

function getSignedGoogleCloudStorageUrl($filepath, $bucket, $secret, $key, $duration = 300)
{
    $expires = new \DateTime('+ ' . $duration . ' seconds');
    $seconds = $expires->format('U');

    $objectPieces = explode('/', $filepath);
    array_walk($objectPieces, function (&$piece) {
        $piece = rawurlencode($piece);
    });
    $objectName = implode('/', $objectPieces);

    $resource = sprintf(
        '/%s/%s',
        $bucket,
        $objectName
    );

    $headers = []; // you may add any headers needed here

    $toBeSignedArray = [
        'GET',
        '', // contentMd5, can be left blank
        '', // contentType, can be left blank
        $seconds,
        implode("\n", $headers) . $resource,
    ];

    $toBeSignedString = implode("\n", $toBeSignedArray);
    $encodedSignature = urlencode(base64_encode(hash_hmac('sha1', $toBeSignedString, $secret, true)));

    $query   = [];
    $query[] = 'GoogleAccessId=' . $key;
    $query[] = 'Expires=' . $seconds;
    $query[] = 'Signature=' . $encodedSignature;

    return "https://storage.googleapis.com/{$bucket}/{$filepath}?" . implode('&', $query);
}

echo getSignedGoogleCloudStorageUrl($filepath, $bucket, $secret, $key);

?>

However, it always produces the same result after the 1st use until I clear the cache on the web server.

Any help or other working examples would be great. Thanks.

bob williams
  • 73
  • 1
  • 8
  • 1
    "it always produces the same result" Can you explain in detail what is the output or any errors? – Dharmaraj Aug 30 '21 at 10:57
  • It always produces the same URL. After 5 minutes, it's no good. – bob williams Aug 30 '21 at 11:53
  • `header("Cache-Control: no-cache");` This helped. – bob williams Aug 30 '21 at 13:02
  • Note: your code implements V2 signing which is legacy. V4 signing is recommended today. However, that method is fairly complicated to implement in raw PHP. I recommend that you switch to using the **google/cloud-storage** SDK. Then your code becomes simpler and up to date. – John Hanley Aug 30 '21 at 18:23
  • Thanks for sharing your code fragment. I work with a legacy PHP project, and I cannot use the SDK. This greatly helps me to move functionality out of the app into the cloud <3 – Haplo May 18 '22 at 13:04

0 Answers0