You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP AWS SDK生成无效S3预签名URL,报SignatureDoesNotMatch错误

S3预签名URL生成时SignatureDoesNotMatch错误排查

问题场景

使用以下PHP代码生成S3预签名PutObject URL时,调用URL出现签名不匹配错误:

public function generatePreSignedUrl(): string
{
    $secretAccessKey = urlencode(env('AWS_SECRET_ACCESS_KEY'));
    $bucket = env('AWS_BUCKET');
    $client = new S3Client([
        'version' => 'latest',
        'region' => env('AWS_DEFAULT_REGION'),
        'credentials' => [
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => $secretAccessKey,
        ],
    ]);

    $expires = Carbon::now()->addMinutes(15)->timestamp;

    $keyname = 'video.mp4';
    
    $command = $client->getCommand('PutObject', [
        'Bucket' => $bucket,
        'Key' => $keyname,
        'ContentType' => 'video/mp4',
    ]);

    $request = $client->createPresignedRequest($command, $expires);
    return (string) $request->getUri();
}

错误信息:

return (<Code>SignatureDoesNotMatch</Code>
)
return (<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
)

核心原因及解决方法

核心原因

错误地对AWS_SECRET_ACCESS_KEY执行了urlencode()处理。AWS SDK在计算签名时会自行处理密钥的编码逻辑,手动URL编码会篡改原始密钥值,导致签名计算结果与AWS服务端校验的签名不一致。

解决方法

移除对密钥的urlencode()操作,直接使用原始密钥值初始化S3客户端。修正后的代码如下:

public function generatePreSignedUrl(): string
{
    $secretAccessKey = env('AWS_SECRET_ACCESS_KEY'); // 移除urlencode处理
    $bucket = env('AWS_BUCKET');
    $client = new S3Client([
        'version' => 'latest',
        'region' => env('AWS_DEFAULT_REGION'),
        'credentials' => [
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => $secretAccessKey,
        ],
    ]);

    $expires = Carbon::now()->addMinutes(15)->timestamp;

    $keyname = 'video.mp4';
    
    $command = $client->getCommand('PutObject', [
        'Bucket' => $bucket,
        'Key' => $keyname,
        'ContentType' => 'video/mp4',
    ]);

    $request = $client->createPresignedRequest($command, $expires);
    return (string) $request->getUri();
}

其他排查方向

如果问题仍存在,可检查以下常见点:

  • 确认AWS_DEFAULT_REGION与存储桶实际所在区域完全一致,区域不匹配会导致签名计算逻辑出错。
  • 验证AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY是否有效,确保密钥拥有对应存储桶的PutObject权限。
  • 上传请求时的ContentType必须与生成签名时指定的video/mp4完全一致,任何请求参数的变更都会导致签名不匹配。
  • 检查服务器系统时间是否与标准UTC时间同步,时间偏差超过5分钟会触发签名过期校验失败。

内容的提问来源于stack exchange,提问作者Erick Scur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 22:55:16