使用AWS JavaScript SDK v3调用S3接口时遇SignatureDoesNotMatch错误
我正在搭建一个将文件上传至S3存储桶的Node.js应用,持续遇到错误:
SignatureDoesNotMatch : The request signature we calculated does not match the signature you provided.
为简化测试,我用以下代码尝试获取存储桶列表:
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; const s3Client = new S3Client({ region: "us-west-2", credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, }, }); try { const data = await s3Client.send(new ListBucketsCommand({})); console.log("Success", data.Buckets); } catch (err) { console.log("Error", err); }
我的IAM用户创建步骤:
- 创建新用户:IAM控制台 > 访问管理 > 用户 > 创建用户
- 设置权限:第二步 > 设置权限 > 创建用户组 > 添加权限策略 > 将用户加入组 > 创建管理员组并附加AdministratorAccess策略
- 创建访问密钥:用户详情页 > 创建访问密钥(用于本地代码)
我试过的配置方式:AWS CLI配置、手动添加本地配置文件、直接通过环境变量传入S3Client构造函数。确认代码执行时环境变量值正确,且用VS Code的AWS扩展通过同一本地配置文件(s3-uploader-user配置文件)能正常查看us-west-2区域的S3存储桶并上传文件,说明权限没问题。
可能的解决方向
1. 同步系统时间
AWS签名验证对时间精度要求很高,如果本地机器时间与AWS服务器时间偏差超过5分钟,就会触发签名不匹配错误。手动开启系统自动时间同步,或者手动校准时间后重试。
2. 清理凭证的多余空格
检查环境变量里的AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY是否带有前后空格——复制粘贴时很容易出现这种问题。可以在代码里加个trim()处理:
credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID?.trim(), secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY?.trim(), },
3. 简化凭证配置逻辑
不要在代码里手动传入credentials,让SDK自动读取默认凭证链(本地配置文件、环境变量、IAM角色等),避免手动配置的潜在错误:
const s3Client = new S3Client({ region: "us-west-2" });
同时确保本地~/.aws/credentials和~/.aws/config文件的配置正确,区域与代码指定的一致。
4. 更新SDK版本
不同版本的AWS SDK可能存在签名算法的兼容性问题,把相关依赖更到最新版试试:
npm update @aws-sdk/client-s3 @aws-sdk/lib-storage
5. 排查代理或网络干扰
如果你的机器通过代理访问AWS,代理可能会修改请求头或内容,导致签名验证失败。尝试关闭代理后测试,或者在S3Client中配置正确的代理参数:
import { NodeHttpHandler } from "@aws-sdk/node-http-handler"; const s3Client = new S3Client({ region: "us-west-2", requestHandler: new NodeHttpHandler({ proxy: "http://你的代理地址:端口", }), });
内容的提问来源于stack exchange,提问作者Ian Tunbridge

