Amazon SES HTTPS 查询 API 身份验证错误

Amazon SES HTTPS Query API Authentication error

我一直在尝试使用 Amazon SES Https 查询 API 发送电子邮件。 但是我计算并发送到 aws 的签名不被接受。

我收到此错误消息。

<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", "bhanuka.yd@gmail.com"));
    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", "test@test.com"));

    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();

所以我在这里做错了什么, 请有人帮助我 谢谢。

我终于发现我可以使用 Signature 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());
}