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

如何用Python生成AWS签名?签名过期及生成失败问题求助

AWS Signature Version 4签名错误排查与修复

遇到的错误

{"message":"Signature expired: 20220813T114319Z is now earlier than 20220813T114400Z (20220813T114900Z - 5 min.)"}

代码问题分析

1. 签名过期原因

请求中硬编码了X-Amz-Date为20220813T114319Z,该时间早于当前服务器时间5分钟以上。AWS要求请求的时间戳与服务器UTC时间差不得超过5分钟,否则会触发签名过期错误。

2. 签名生成代码的核心错误

  • Service名称错误:调用API Gateway服务时,service参数应为execute-api,而非sao-francisco,签名生成时的服务名称必须与实际调用的AWS服务匹配。
  • Canonical URI错误:canonical_uri应该是请求的路径部分(不含协议和主机),正确值为/prod/fulfillmentManagers/xxxxxxxxxx/fulfillments/zzzzzzzzzz,而非完整的endpoint URL。
  • Headers不匹配:签名生成时的canonical_headers和signed_headers未包含实际请求中的Content-Type、X-Amz-Security-Token、X-UserId,且header名未统一为小写(AWS要求header名小写)。
  • Authorization格式错误:Credential字段中datestamp前多了空格,Signature字段前也多了空格,AWS对签名格式的空格要求严格,多余空格会导致签名验证失败。

修复后的完整代码

import datetime, hashlib, hmac, requests

access_key = "你的AccessKey"
secret_key = "你的SecretKey"
session_token = "你的SessionToken"
method = 'GET'
service = 'execute-api'  # 修正为API Gateway的服务名称
host = 'yyyyyyyyyy.execute-api.us-east-1.amazonaws.com'
region = 'us-east-1'
endpoint = f'https://{host}'
path = '/prod/fulfillmentManagers/xxxxxxxxxx/fulfillments/zzzzzzzzzz'

def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning

# 获取当前UTC时间,确保签名和请求时间一致
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')

# 构造Canonical URI(仅路径部分)
canonical_uri = path

# 构造Canonical Headers,包含所有请求header,且名称小写
canonical_headers = (
    f'content-type:application/x-amz-json-1.1\n'
    f'host:{host}\n'
    f'x-amz-date:{amz_date}\n'
    f'x-amz-security-token:{session_token}\n'
    f'x-userid:bob\n'
)

# Signed Headers需与Canonical Headers一一对应,小写,分号分隔
signed_headers = 'content-type;host;x-amz-date;x-amz-security-token;x-userid'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = f'{datestamp}/{region}/{service}/aws4_request'
canonical_querystring = ''
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()

# 构造Canonical Request
canonical_request = (
    f'{method}\n'
    f'{canonical_uri}\n'
    f'{canonical_querystring}\n'
    f'{canonical_headers}\n'
    f'{signed_headers}\n'
    f'{payload_hash}'
)

# 构造String to Sign
string_to_sign = (
    f'{algorithm}\n'
    f'{amz_date}\n'
    f'{credential_scope}\n'
    f'{hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()}'
)

# 生成签名密钥和签名
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()

# 构造Authorization头,注意格式无多余空格
authorization_header = (
    f'AWS4-HMAC-SHA256 Credential={access_key}/{credential_scope}, '
    f'SignedHeaders={signed_headers}, '
    f'Signature={signature}'
)

# 构造请求headers
headers = {
    'Content-Type': 'application/x-amz-json-1.1',
    'X-UserId': 'bob',
    'X-Amz-Security-Token': session_token,
    'X-Amz-Date': amz_date,
    'Authorization': authorization_header
}

# 发送请求
url = f'{endpoint}{path}'
response = requests.request(method, url, headers=headers, data='')
print(response.text)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:57:19