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

S3预签名PUT URL签名不匹配问题及公开URL生成咨询

解决S3预签名URL上传的SignatureDoesNotMatch错误及相关疑问

我来逐个解答你的问题,顺便帮你排查curl测试失败的核心原因:

1. 错误中的密钥是否指IAM颁发的AWS凭证密钥?

是的,错误里提到的密钥就是IAM生成的AWS访问密钥对(Access Key ID和Secret Access Key)。AWS通过对比请求携带的签名与服务端计算出的签名,来验证请求的合法性,当两者不匹配时就会抛出这个错误。

2. Lambda生成预签名URL时使用的是哪个密钥?

你的Lambda函数不会使用你本地的AWS密钥,它运行时会自动从AWS元数据服务获取临时IAM凭证,这些凭证对应你给Lambda配置的执行角色。你需要确保这个执行角色拥有s3:PutObject权限,且权限范围覆盖目标S3存储桶和你指定的${CONFIG.s3PictureFolder}/前缀路径。

3. 如何生成供用户上传文件的公开预签名URL?

预签名URL本身就是为了让没有AWS账号的用户能上传文件而设计的,如果你希望上传后的文件可以公开访问,可以做以下调整:

调整Lambda代码添加公开ACL

在生成预签名URL的params中加入ACL: 'public-read'参数,这样用户通过该URL上传的文件会自动设置为公开可读:

export const getSignedURL = async (): Promise<{ signedURL: string }> => {
  try {
    const s3 = new S3();
    const params = {
      Bucket: CONFIG.s3Bucket,
      Key: `${CONFIG.s3PictureFolder}/${uuidv4()}`,
      Expires: CONFIG.presignedURLExpires,
      ACL: 'public-read' // 添加这一行,指定上传后文件的公开权限
    };
    const signedURL = await s3.getSignedUrlPromise('putObject', params);
    console.log(`generate signedURL url: ${signedURL}`);
    return { signedURL };
  } catch (err) {
    console.error(err);
    throw err;
  }
};

修正curl测试命令

你当前的curl命令用--data "my data"会导致请求内容类型与预签名URL生成时的预期不匹配,这也是SignatureDoesNotMatch错误的常见诱因之一。正确的测试方式分两种:

  • 上传本地文件:用-T参数指定文件路径
    curl -XPUT -T "your-local-file.jpg" PRESIGNED_URL
    
  • 上传文本数据:显式指定内容类型(和预签名URL生成时的默认类型binary/octet-stream保持一致)
    curl -XPUT -H "Content-Type: binary/octet-stream" --data "my data" PRESIGNED_URL
    

额外注意点:

  • 确保Lambda执行角色的权限策略允许设置public-read ACL(一般包含s3:PutObject权限即可,因为该操作默认允许附带ACL设置)
  • 预签名URL的有效期由Expires参数控制,测试时要确保URL还在有效期内

内容的提问来源于stack exchange,提问作者Joey Yi Zhao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:57:42