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

Lambda生成S3预签名POST URL上传报SignatureDoesNotMatch错误

S3 预签名POST上传触发SignatureDoesNotMatch问题定位与修复

核心错误根源

你完全混淆了S3两类预签名上传的协议规范,把generate_presigned_post()对应的POST表单上传逻辑,错用成了预签名URL上传的参数拼接方式,导致S3端计算的校验签名和你提交的内容完全不匹配。

具体错误点

  • URL拼接逻辑完全错误
    generate_presigned_post()返回的url字段本身就是POST请求的目标地址,不需要在后面拼接对象Key,也不需要把签名、凭证类参数拼到URL的查询串里。你当前代码里手写拼接带一堆X-Amz-*参数的URL路径,本身就不符合S3 POST预签名的请求结构要求。
  • 漏提交必填的表单字段
    你当前的FormData里只上传了文件本身,没有把返回的fields对象里的所有键值对(包括key、x-amz-algorithm、x-amz-credential、x-amz-date、x-amz-security-token、x-amz-signature、policy)作为表单项提交。POST预签名的规则要求所有凭证类字段必须放在请求体的表单段中,而不是URL查询参数里,字段缺失自然无法通过签名校验。
  • 表单字段提交顺序错误
    即便把所有字段都加入FormData,也必须注意提交顺序:所有预签名返回的fields字段要在文件字段之前append,文件字段必须是FormData里最后一个表单项,否则S3解析表单的时候无法匹配policy定义的字段顺序,也会触发签名不匹配错误。
  • 代码里手动注释了policy字段的传递逻辑,这个字段是POST预签名的核心校验依据,缺少它S3根本无法回溯你生成签名时的规则定义。
  • 多余的类型转换逻辑
    根据你给出的接口返回结构,signed_url字段本身是包含url和fields的对象,不是序列化后的字符串,你代码里执行JSON.parse(data["signed_url"])会直接触发类型转换错误,即便侥幸拿到值,也是解析出的错误结构。
  • 对x-amz-security-token字段手动做了encodeURIComponent编码,SDK生成的字段值本身已经符合表单提交的格式要求,过度编码会导致提交的值和生成签名时的原始值不一致,也会触发签名不匹配。

正确实现方式

Lambda侧的generate_presigned_post()调用逻辑不需要修改,只需要调整客户端的上传逻辑即可,正确代码参考如下:

function uploadToS3(data){
    const form = new FormData();
    // 直接取返回的POST目标URL,不做任何拼接、JSON.parse处理
    const postUrl = data["signed_url"]["url"]
    const fields = data["signed_url"]["fields"]
    // 先把所有预签名返回的字段逐个加入FormData,不做手动编码
    Object.keys(fields).forEach(key => {
        form.append(key, fields[key])
    })
    // 最后再把文件加入FormData,保证是最后一个表单项
    const uploadFile = $('#customFile1').get()[0].files[0]
    form.append("file", uploadFile)

    $.ajax({
        type : 'POST',
        url: postUrl,
        data: form,
        processData: false,
        contentType: false,
        success:function(resp){
            console.log("上传成功", resp)
        },
        error:function(resp) {
            console.log("上传失败", resp);
        }
    })
}

额外注意事项

  • ExpiresIn=30的过期时间非常短,要注意客户端拿到凭证后立刻发起上传,不要留过长的用户操作等待时间,否则会触发凭证过期错误。
  • 如果你的S3桶开启了强制SSL访问,要确保返回的url字段是https开头的地址,避免因为协议不匹配触发访问拒绝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 07:45:04