2016-05-28 4 views
0

Я пытаюсь отправить электронное письмо с использованием API запросов Amazon SES Https. , но подпись, которую я рассчитываю и отправляю в aws, не принимается.Ошибка проверки подлинности API запроса API-запроса Amazon SES HTTPS

Получаю это сообщение об ошибке.

<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>c97bd130-24c9-11e6-924a-b59d7ac9182b</RequestId> 
</ErrorResponse> 

вот мой код Java

public class SendSESMail { 
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SignatureException { 
    SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z"); 
    String dateString = format.format(new Date()); 

    final String ENDPOINT = "https://email.us-east-1.amazonaws.com"; 
    final String AWS_ACCESS = "ACCESS_KEY"; 
    final String AWS_SECRET = "SECRET_KEY"; 

    CloseableHttpClient httpClient = HttpClients.createDefault(); 
    HttpPost post = new HttpPost(ENDPOINT); 

    String authString = generateAuthHeader(AWS_ACCESS, AWS_SECRET, dateString); 

    List<NameValuePair> formVals = new ArrayList<>(); 
    formVals.add(new BasicNameValuePair("Action", "SendRawEmail")); 
    formVals.add(new BasicNameValuePair("Destination.ToAddresses.member.1", "[email protected]")); 
    formVals.add(new BasicNameValuePair("Message.Body.Text.Data", "I hope you see the body.")); 
    formVals.add(new BasicNameValuePair("Message.Subject.Data", "This is a Unique Subject")); 
    formVals.add(new BasicNameValuePair("Source", "[email protected]")); 

    UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formVals); 

    post.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString()); 
    post.setHeader("Date", dateString); 
    post.setHeader("X-Amzn-Authorization", authString); 

    post.setEntity(formEntity); 
    HttpResponse response = httpClient.execute(post); 
    response.getEntity().writeTo(System.out); 

} 

public static String generateAuthHeader(String accessKey, String secret, String dateString) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException { 
    String authHeaderVal = "AWS3-HTTPS AWSAccessKeyId=" + accessKey + ",Algorithm=HmacSHA256,Signature="; 
    authHeaderVal += generateSignature(dateString, secret); 
    return authHeaderVal; 
} 

public static String generateSignature(String message, String secret) throws NoSuchAlgorithmException, InvalidKeyException { 
    Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); 
    SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); 
    sha256_HMAC.init(secretKey); 
    return Base64.encodeBase64URLSafeString(sha256_HMAC.doFinal(message.getBytes())); 
} 
} 

в первый раз я попробовал его, он дал мне эту ошибку

<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/"> 
<Error> 
    <Type>Sender</Type> 
    <Code>ValidationError</Code> 
    <Message>1 validation error detected: Value null at 'rawMessage' failed to satisfy constraint: Member must not be null</Message> 
</Error> 
<RequestId>9a986157-24ca-11e6-9864-3fdeb433e3c8</RequestId> 
</ErrorResponse> 

это было потому, что подпись была «=» знак в конце, поэтому я использовал

encodeBase64URLSafeString(); 

метод для преобразования подписи в Base64 вместо

encodeBase64String(); 

Так что я здесь делаю неправильно, Пожалуйста, кто-то помочь мне здесь спасибо.

+0

Я думаю, что строка, которую вы подписываете, неверна. Хотя это не тот же сервис, здесь приведен пример фрагмента кода Java для подписания aws-запроса HTTP с сигнатурой версии 2.http: //docs.aws.amazon.com/AWSECommerceService/latest/DG/AuthJavaSampleSig2.html – Shibashis

+0

, но здесь http: //docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface-authentication.html он говорит «Чтобы создать строку для подписи, вычислить хеш-маркер HMAC, совместимый с RFC 2104, со значением заголовка Date, секретный ключ доступа в качестве ключа, а SHA256 или SHA1 в качестве алгоритма хеширования « –

+0

- это именно то, что я сделал. за исключением того, что при преобразовании в Base64 я использовал версию URLSafe, а не обычный. потому что обычный имеет знак «=», который вызывает другую ошибку. –

ответ

0

Наконец-то выяснилось, что я могу использовать подпись V4 для аутентификации моего HTTP-запроса.

любой, у кого есть эта проблема, может следовать точному процессу ниже link, и вы сможете пройти аутентификацию.

Одна вещь, чтобы иметь в виду, что время запроса должно быть в формате ISO8601, в UTC

здесь метод, чтобы вычислить текущее время в формате UTC часовой пояс.

public static String getUTCTimeISO8601Format() { 
    TimeZone timeZone = TimeZone.getTimeZone("UTC"); 
    Calendar calendar = Calendar.getInstance(timeZone); 
    SimpleDateFormat iso8601Format = new SimpleDateFormat("YYYYMMdd'T'HHmmss'Z'");//ISO8601 B8601DZw.d format 
    iso8601Format.setTimeZone(timeZone); 
    return iso8601Format.format(calendar.getTime()); 
} 
Смежные вопросы