如何从 Java 在 AWS 中生成签名

新手上路,请多包涵

当我从 REST 客户端调用 API 端点时,我因与签名有关而出错。

要求:

主机https ://xxx.execute-api.ap-southeast-1.amazonaws.com/latest/api/name

授权:AWS4-HMAC-SHA256 Credential= {AWSKEY} /20160314/ap-southeast-1/execute-api/aws4_request,SignedHeaders=host;range;x-amz-date,Signature= {signature}

X-Amz-日期:20160314T102915Z

回复:

 {
"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. The Canonical String for this request should have been 'xxx' "
}

在 Java 代码中,我遵循了 AWS 对如何生成签名的参考。

     String secretKey = "{mysecretkey}";
    String dateStamp = "20160314";
    String regionName = "ap-southeast-1";
    String serviceName = "execute-api";

    byte[] signature = getSignatureKey(secretKey, dateStamp, regionName, serviceName);
    System.out.println("Signature : " + Hex.encodeHexString(signature));

    static byte[] HmacSHA256(String data, byte[] key) throws Exception  {
         String algorithm="HmacSHA256";
         Mac mac = Mac.getInstance(algorithm);
         mac.init(new SecretKeySpec(key, algorithm));
         return mac.doFinal(data.getBytes("UTF8"));
    }

    static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception  {
         byte[] kSecret = ("AWS4" + key).getBytes("UTF8");
         byte[] kDate    = HmacSHA256(dateStamp, kSecret);
         byte[] kRegion  = HmacSHA256(regionName, kDate);
         byte[] kService = HmacSHA256(serviceName, kRegion);
         byte[] kSigning = HmacSHA256("aws4_request", kService);
         return kSigning;
    }

我可以知道我在生成签名时出了什么问题吗?

参考如何生成签名: http ://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java

原文由 Tun Lin Aung 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 917
1 个回答

您可以使用 aws-java-sdk-core 中的类: https ://github.com/aws/aws-sdk-java/tree/master/aws-java-sdk-core

更具体地说,Request、Aws4Signer 和其他几个:

 //Instantiate the request
Request<Void> request = new DefaultRequest<Void>("es"); //Request to ElasticSearch
request.setHttpMethod(HttpMethodName.GET);
request.setEndpoint(URI.create("http://..."));

//Sign it...
AWS4Signer signer = new AWS4Signer();
signer.setRegionName("...");
signer.setServiceName(request.getServiceName());
signer.sign(request, new AwsCredentialsFromSystem());

//Execute it and get the response...
Response<String> rsp = new AmazonHttpClient(new ClientConfiguration())
    .requestExecutionBuilder()
    .executionContext(new ExecutionContext(true))
    .request(request)
    .errorResponseHandler(new SimpleAwsErrorHandler())
    .execute(new SimpleResponseHandler<String>());

如果你想要一个更简洁的设计,你可以使用装饰器模式来组合一些优雅的类并隐藏上面的混乱。这里的一个例子:http: //www.amihaiemil.com/2017/02/18/decorators-with-tunnels.html

原文由 amihaiemil 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题