0

我正在尝试遵循AWS SigV4 签名过程文档中的代码,但似乎有些不对劲,因为我不断收到错误 403 - signature does not match

我所做的只是根据需要更改参数。我一直在 Postman 中使用相同的参数,它们完美地工作。

这是我的 Python 代码,直接来自文档:

import sys, datetime, hashlib, hmac
import requests
import const

# ************* REQUEST VALUES *************
method = 'GET'
service = 'sts'
host = 'sts.eu-west-1.amazonaws.com'
region = 'eu-west-1'
endpoint = 'https://sts.eu-west-1.amazonaws.com'
request_parameters = 'Action=AssumeRole&Version=2011-06-15&RoleArn=arn:aws:iam::mySessionName:role/SellingPartnerAPIRole&DurationSeconds=3600&RoleSessionName=mySessionName'

# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

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

access_key = const.AWS_ACCESS_KEY_ID
secret_key = const.AWS_SECRET_ACCESS_KEY
if access_key is None or secret_key is None:
    print('No access key is available.')
    sys.exit()

# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')  # Date w/o time, used in credential scope

# ************* TASK 1: CREATE A CANONICAL REQUEST *************
canonical_uri = '/'
canonical_querystring = request_parameters
canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'
signed_headers = 'host;x-amz-date'
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash

# ************* TASK 2: CREATE THE STRING TO SIGN*************
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + hashlib.sha256(
    canonical_request.encode('utf-8')).hexdigest()

# ************* TASK 3: CALCULATE THE SIGNATURE *************
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()

# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
headers = {'x-amz-date': amzdate, 'Authorization': authorization_header}

# ************* SEND THE REQUEST *************
request_url = endpoint + '?' + canonical_querystring

print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + request_url)
r = requests.get(request_url, headers=headers)

print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % r.status_code)
print(r.text)

我尝试将邮递员的amzdatedatetime签名放入此代码中,并且它们起作用了。所以我认为签名计算过程有问题,但我真的说不出来。

我很感激我能得到的所有帮助。提前致谢。

4

0 回答 0