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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:06:04