如何通过AWS Signature 4授权访问API Gateway与Lambda 生成签名返回403
问题描述
我搜索了大量资料仍未找到问题解决方案,已通读AWS Signature 4完整认证流程,跟随官方教程操作同时也参考了其他资料,需要为向API Gateway发起请求的桌面应用实现客户端侧认证。
使用Postman发起请求可以正常响应,但我尝试在Node.js中自行生成签名始终失败,调用后持续返回403错误。
下方函数会返回经过认证的requestUrl,随后通过axios.get(requestUrl)发起请求。使用Postman生成的请求可以正常运行,但使用我自行生成的请求就会出现问题,请问我在认证过程中是否遗漏了什么?当前代码如下:
function Authorize() { const host = "EXAMPLE.execute-api.us-east-1.amazonaws.com" const reg = 'us-east-1' const meth = 'GET' const serv = 'execute-api' const endpoint = '/development/putImage' // Keys let access = "EXAMPLE" let key = "KEY" // Get Date let t = new Date(); let amzDate = t.toJSON().replace(/[-:]/g, "").replace(/\.[0-9]*/, ""); let dateStamp = t.toJSON().replace(/-/g, "").replace(/T.*/, ""); // ************* TASK 1: CREATE CANONICAL REQUEST ************* // Create Canonical Request let canonical_uri=endpoint let canonical_headers="host: "+host+"\n" let signedHeaders = 'host' let algorithm = 'AWS4-HMAC-SHA256' let credentialScope = dateStamp + "/" + reg + "/" + serv + "/" + "aws4_request" // Set query string let canonicalQueryString = "" canonicalQueryString += "X-Amz-Date=" + amzDate canonicalQueryString += "&X-Amz-Algorithm=" + algorithm; canonicalQueryString += "&X-Amz-Credential=" + encodeURIComponent(access + "/" + credentialScope) canonicalQueryString += "&X-Amz-SignedHeaders=" + signedHeaders // Empty payload for get request var payloadHash = crypto.createHash('sha256').update('').digest('hex'); // Set canonical request var canonicalRequest = meth + "\n" + canonical_uri + "\n" + canonicalQueryString + "\n" + canonical_headers + "\n" + signedHeaders + "\n" + payloadHash console.log(canonicalRequest) // ************* TASK 2: CREATE THE STRING TO SIGN************* let stringToSign = algorithm + '\n' + amzDate + '\n' + credentialScope + '\n' + crypto.createHash('sha256').update(canonicalRequest).digest('hex'); // ************* TASK 3: CALCULATE THE SIGNATURE ************* var signingKey = getSignatureKey(key, dateStamp, reg, serv) var signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex'); // ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST ************* canonicalQueryString += '&X-Amz-Signature=' + signature let requestUrl = "https://"+host+ endpoint + "?" + canonicalQueryString console.log(requestUrl) return requestUrl }
修复方案
核心问题:规范查询字符串排序错误
AWS Signature V4强制要求规范查询字符串的所有参数必须按照参数名的ASCII码顺序从小到大排序,你当前的参数顺序不符合要求,这是签名失败的最常见诱因。正确的排序后顺序应为X-Amz-Algorithm → X-Amz-Credential → X-Amz-Date → X-Amz-SignedHeaders,调整拼接代码如下:
// 修正排序后的查询字符串拼接逻辑 let canonicalQueryString = "" canonicalQueryString += "X-Amz-Algorithm=" + algorithm; canonicalQueryString += "&X-Amz-Credential=" + encodeURIComponent(access + "/" + credentialScope) canonicalQueryString += "&X-Amz-Date=" + amzDate canonicalQueryString += "&X-Amz-SignedHeaders=" + signedHeaders
其他必检项
- 校验
getSignatureKey函数实现,必须每一步返回二进制Buffer而非十六进制字符串,正确实现如下:function getSignatureKey(key, dateStamp, regionName, serviceName) { const kDate = crypto.createHmac('sha256', 'AWS4' + key).update(dateStamp).digest(); const kRegion = crypto.createHmac('sha256', kDate).update(regionName).digest(); const kService = crypto.createHmac('sha256', kRegion).update(serviceName).digest(); const kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest(); return kSigning; } - 同步本地设备时钟,AWS要求签名生成时间与服务器时间差不能超过15分钟,否则直接返回403错误。
- 对比Postman生成的请求参数与你的代码输出,确认AK/SK、区域、服务名、接口路径完全一致,同时确认axios没有自动添加额外请求头,如有额外参数必须同步加入规范头和签名头列表中。
内容的提问来源于stack exchange,提问作者Kyle Watkins
相关产品推荐
相关产品推荐

