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

时间:2016-05-28 11:57:34

标签: amazon-web-services hmac amazon-ses

我一直在尝试使用Amazon SES Https Query 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();

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

1 个答案:

答案 0 :(得分:0)

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