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

Postman调用S3预签名POST URL返回SignatureDoesNotMatch错误排查

S3预签名POST 403 SignatureDoesNotMatch问题解答

1. 调用方式正确性校验

你对预签名POST的核心调用逻辑是正确的,但存在几个容易踩的细节问题,符合以下要求才算完全正确的调用:

  • form-data字段必须严格按照createPresignedPost返回的fields顺序填充,所有返回字段不能遗漏、顺序不能调换,否则直接触发签名不匹配
  • file字段必须放在所有form字段的最后一位,不能插入到其他字段中间
  • 你的代码中配置了Conditions: [["eq", "$Content-Type", "image/jpeg"]],因此请求必须携带Content-Type字段,且值必须完全等于image/jpeg,不能用image/jpg等别名,也不能加额外参数
  • Postman中不要手动添加Authorization、Content-Type等请求头,form-data格式的Content-Type会自动携带边界值,手动填写会覆盖自动生成的边界配置导致请求异常

2. 调试定位方法

  • 首先打印S3返回的完整403响应头,提取x-amz-signature-provided和x-amz-string-to-sign字段,和本地生成签名时的字符串做对比,差异点就是签名错误的原因
  • 优先排除Postman的干扰,直接用Node.js代码发起测试请求,示例如下:
const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');

// 调用你封装的getSignedUrl方法获取签名结果
const { url, fields } = await getSignedUrl();
const form = new FormData();
// 按顺序插入所有返回的fields
Object.entries(fields).forEach(([key, value]) => form.append(key, value));
// 插入和条件匹配的Content-Type
form.append('Content-Type', 'image/jpeg');
// 最后插入文件
form.append('file', fs.readFileSync('./测试用的jpeg图片路径'), { 
  filename: 'test.jpg', 
  contentType: 'image/jpeg' 
});

await axios.post(url, form, { headers: form.getHeaders() });
  • 存储桶日志本身有1-2小时的生成延迟,刚操作完看不到日志属于正常现象,不需要等日志输出,用上面的代码测试效率更高

3. 额外排查点

  • 检查生成预签名的服务器系统时间,如果和AWS标准时间偏差超过15分钟,会直接导致签名失效
  • 检查S3存储桶是否开启了KMS默认加密,如果开启需要在生成预签名的参数中补充KMS相关配置,或在Conditions中添加加密规则的匹配条件
  • 确认预签名的有效期,createPresignedPost默认有效期为3600秒,超过有效期后调用也会返回签名错误
  • 确认生成预签名用的IAM账号有s3:PutObject权限,且没有配置权限边界、会话策略等限制上传操作的规则
  • 确认你没有修改返回的fields中任何字段的值,包括policy、signature等字段,任何字符变动都会导致签名不匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:48:01