使用AWS4-HMAC-SHA256签名请求时遇SignatureDoesNotMatch错误排查
解决AWS STS AssumeRole请求的SignatureDoesNotMatch错误
问题根源
你的代码对aws4.sign的path参数设置错误——你把包含协议和域名的完整URL传给了path,但AWS签名计算规则里,path应该仅包含域名之后的部分(即从/?开始的路径与查询字符串)。这种不匹配导致签名计算的请求内容和实际发送的请求内容不一致,最终触发签名验证失败。
修复步骤
- 拆分URL结构:将完整的请求地址拆分为
host(域名部分)和path(路径+查询参数部分),避免把协议和域名混入path。 - 修正签名参数:确保
aws4.sign的path参数只传入拆分后的路径部分,和实际请求的路径保持完全一致。 - 保持请求URL正确:fetch请求仍使用完整的
endpoint,但签名逻辑必须基于正确的拆分参数。
修正后的代码
import * as aws4 from 'aws4' async getStsCredentials() { const awsCredentials = { accessKeyId: 'xxx', secretAccessKey: 'xxx', region: 'us-east-1', }; const params = { RoleArn: 'xxx', RoleSessionName: 'test', DurationSeconds: 3600, }; // 拆分host和path,避免将完整URL传入签名的path参数 const host = `sts.${awsCredentials.region}.amazonaws.com`; const path = `/?Version=2011-06-15&Action=AssumeRole&RoleSessionName=${params.RoleSessionName}&RoleArn=${encodeURIComponent(params.RoleArn)}&DurationSeconds=${params.DurationSeconds}`; const endpoint = `https://${host}${path}`; const signedRequest = aws4.sign( { service: 'sts', region: awsCredentials.region, method: 'GET', host: host, path: path, // 这里仅传入路径+查询参数,而非完整URL }, awsCredentials ); // 发送请求 fetch(endpoint, { headers:{ 'Authorization': signedRequest.headers.Authorization as string, 'x-amz-date': signedRequest.headers['X-Amz-Date'] as string } }) .then((response) => response.text()) .then((result) => console.log(result)) .catch((error) => console.log('error', error)); }
额外注意事项
- 确认
RoleArn已用encodeURIComponent正确编码特殊字符,避免查询参数解析异常。 - HTTP请求头大小写不敏感,但建议保持
x-amz-date与签名生成的X-Amz-Date一致,减少潜在的兼容性问题。
内容的提问来源于stack exchange,提问作者Horuge
相关产品推荐
相关产品推荐

