Получение ответа 403 при подписании запроса Amazon - PullRequest
0 голосов
/ 16 февраля 2019

Я пытаюсь отправить электронное письмо через Amazon SES без SDK, чтобы я мог отправлять электронные письма асинхронно в Python.Я использую метод подписи amazon v4 на их сайте здесь: https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html,, но мне не повезло отправлять электронные письма без SDK.Вывод:

RESPONSE++++++++++++++++++++++++++++++++++++
Response code: 403

<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
  <Error>
    <Type>Sender</Type>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message>
  </Error>
  <RequestId>a19a5fa1-3228-11e9-b2bc-ddb6d8a1cb1c</RequestId>
</ErrorResponse>


Process finished with exit code 0

Вот блок кода, генерирующий этот ответ:

import datetime
import hashlib
import hmac
import urllib.parse
import requests
method = 'GET'
service = 'ses'
host = 'email.us-east-1.amazonaws.com'
region = 'us-east-1'
endpoint = 'https://email.us-east-1.amazonaws.com/'


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


access_key = '<my access_key here>'
secret_key = '<my secret_key here>'
my_email = 'my email here'


t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
canonical_uri = '/'
canonical_headers = 'host:' + host + '\n'
signed_headers = 'host'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'

canonical_querystring = '''Action=SendEmail
&Source=%s%40gmail.com
&Destination.ToAddresses.member.1=%s%40gmail.com
&Message.Subject.Data=This%20is%20the%20subject%20line.
&Message.Body.Text.Data=Hello.%20I%20hope%20you%20are%20having%20a%20good%20day''' % (my_email, my_email)

canonical_querystring += '&X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
canonical_querystring += '&X-Amz-Date=' + amz_date
canonical_querystring += '&X-Amz-Expires=30'
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers

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
string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  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()
canonical_querystring += '&X-Amz-Signature=' + signature
request_url = endpoint + "?" + canonical_querystring

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

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

Это в основном код Amazon для генерации подписи, скопированной и вставленной из их документов.Кто-нибудь знает, что я делаю неправильно, подписывая свои запросы к amazon?

Редактировать * Я изменил canonical_querystring на алфавитный примерно так:

canonical_querystring = '''Action=SendEmail
&Destination.ToAddresses.member.1={}%40gmail.com
&Message.Body.Text.Data=Hello.%20I%20hope%20you%20are%20having%20a%20good%20day
&Message.Subject.Data=This%20is%20the%20subject%20line.
&Source={}%40gmail.com'''.format(my_email, my_email)

Это все еще дает мне то же самоеошибка хотя.Все остальное в строке запроса находится в алфавитном порядке или «канонически упорядочено».

1 Ответ

0 голосов
/ 17 февраля 2019

Ваша строка канонического запроса не является канонической.

У вас есть Action... Source... Destination... Message, но все параметры должны быть лексически упорядочены.

Шаг 3: Создайте строку канонического запроса.

[...]

Параметры должны быть отсортированы по имени.

Этот порядок является причиной того, что значение называется canonical .Это необходимо, потому что относительные позиции параметров строки запроса не обязательно гарантированы.Параметры не нужно сортировать в строке запроса фактический , сопровождающей запрос, но они должны быть отсортированы здесь для подписания.

Поскольку данный запрос может иметь только одну возможную действительную подпись, параметры сортируются перед подписанием, чтобы устранить неоднозначность, которая могла бы возникнуть в противном случае, если пользовательский агент или прокси-сервер изменил параметры запроса или упорядочил их произвольно при построении URL-адреса.(как и следовало ожидать, если, например, параметры передаются в UA как неупорядоченная структура хэша / словаря).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...