无法使用 curl 将预签名 url 的文件下载到远程服务器

Cannot download file with presigned url to remote server using curl

我有一个关于使用 AWS S3 预签名 URL 将文件下载到远程服务器的问题。我能够成功地为 zip 文件创建预签名的 URLs。如果我在浏览器中输入预签名的 URL,我就可以成功下载 zip 文件。但是,我还需要我们用户的站点来获取该 zip 文件,将其下载到他们的服务器并解压缩。所以我所做的是使用 PHP CURL 并为 CURLOPT_URL 参数提供预签名的 URL。但是,当我这样做时,zip 文件是空的,并且我收到一条错误消息。由于我使用的是预签名 url,它已经具有下载文件所需的授权和签名 headers。我的问题是为什么它在 PHP CURL 中不起作用,而只在浏览器中起作用?我在这里没有做什么?

示例预签名 URL: https://xxxxxxx-xxxxxxxxxx-xxxxxxx-231481972270.s3-accesspoint.us-east-1.amazonaws.com/serenity-pro/serenity-pro.zip?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIATLZLGSYXEHERUI4Z%2F20210913%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210913T042133Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=62ba2cb3d434f8643cd5099b74523234df46b3c9fdb0f5ab75d962c8ab4d0428

我的代码:

// Download zip file
// The $download_url is the presigned URL I generated for the user
$ch = curl_init();
$fp = fopen($theme_zip_path, "w+");
curl_setopt_array($ch, array(
CURLOPT_URL => $download_url,
CURLOPT_TIMEOUT => 600,
CURLOPT_FILE => $fp
));
$contents = curl_exec($ch);
curl_close($ch);
fclose($fp);

错误信息: InvalidRequest 不支持您提供的授权机制。请使用签名版本 4

如果您的 url 包含 https 则尝试添加这个

CURLOPT_SSL_VERIFYHOST

CURLOPT_SSL_VERIFYPEER

curl_setopt_array($ch, array(
CURLOPT_URL => $download_url,

CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false,

CURLOPT_TIMEOUT => 600,
CURLOPT_FILE => $fp
));

如果有人遇到同样的问题,解决方案是使用 CloudFront 签名 URL。

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.html

// Create a CF signed URL
use Aws\CloudFront\CloudFrontClient;

$resourceKey = $cloudfront_url;
$expires = time() + 1800;
$privateKey = 'YOURPRIVATEKEY.pem';
$keyPairId = 'YOURKEYPAIRID';

$cfClient = new Aws\CloudFront\CloudFrontClient([
    'version' => 'latest',
    'region' => 'YOURREGION',
    'credentials' => $credentials
]);

$download_url = $cfClient->getSignedUrl([
    'url' => $resourceKey,
    'expires' => $expires,
    'private_key' => $privateKey,
    'key_pair_id' => $keyPairId
]);