如何从Java生成AWS签名
当我从REST客户端调用API端点时,我通过关注Signature得到了错误。
请求:
主持人 : 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-Date :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
您可以使用aws-java-sdk-core中的类: https : //github.com/aws/aws-sdk-java/tree/master/aws-java-sdk-core
更具体地说,Request,Aws4Signer和其他一些:
//Instantiate the request Request request = new DefaultRequest ("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 rsp = new AmazonHttpClient(new ClientConfiguration()) .requestExecutionBuilder() .executionContext(new ExecutionContext(true)) .request(request) .errorResponseHandler(new SimpleAwsErrorHandler()) .execute(new SimpleResponseHandler ());
如果你想要一个更干净的设计,你可以使用Decorator模式组成一些优雅的类并隐藏上面的混乱。 这方面的一个例子: http : //www.amihaiemil.com/2017/02/18/decorators-with-tunnels.html
从上面的代码示例看,您似乎没有创建规范请求,并将其包含在根据http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-签名的字符串中。 request.html
你没有自己实现这个,而是考虑使用第三方库。
aws-v4-signer-java是一个轻量级的零依赖库,可以轻松生成AWS V4签名。
String contentSha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; HttpRequest request = new HttpRequest("GET", new URI("https://examplebucket.s3.amazonaws.com?max-keys=2&prefix=J")); String signature = Signer.builder() .awsCredentials(new AwsCredentials(ACCESS_KEY, SECRET_KEY)) .header("Host", "examplebucket.s3.amazonaws.com") .header("x-amz-date", "20130524T000000Z") .header("x-amz-content-sha256", contentSha256) .buildS3(request, contentSha256) .getSignature();
免责声明:我是图书馆作者。
- Servletfilter在AWS上返回“代理错误”
- AWS S3 Java SDK – 拒绝访问
- S3 Java客户端因“Content-Length delimited message body的过早结束”或“java.net.SocketException Socket closed”而失败了很多
- 使用Java Servlet从AWS SimpleDB创建域
- AWS Lambda:如何从简单的java类调用lambda函数
- 在JAVA中使用Lambda的AWS DynamoDB触发器
- 如何通过Pause / Resume支持上传到S3?
- Maven部署包并上传到AWS-Lambda
- Amazon SQS长轮询不返回所有邮件