Comment générer une signature dans AWS à partir de Java


Lorsque j'appelle des points de terminaison API à partir du client REST, j'ai eu une erreur en ce qui concerne la signature.

Demande:

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

Autorisation : 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

Réponse:

{
"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' "
}

À partir du code Java, j'ai suivi la référence AWS sur la façon de générer une signature.

    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;
    }

Puis-je savoir ce que je me suis trompé en générant la Signature?

Référence comment générer une signature : http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java

Author: Tun Lin Aung, 2016-03-14

2 answers

Vous pouvez utiliser les classes d'aws-java-sdk-core: https://github.com/aws/aws-sdk-java/tree/master/aws-java-sdk-core

Plus précisément, Request, Aws4Signer et quelques autres:

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

Si vous voulez un design plus propre, vous pouvez utiliser le motif Décorateur pour composer des classes élégantes et masquer le désordre ci-dessus. Un exemple pour cela ici: http://www.amihaiemil.com/2017/02/18/decorators-with-tunnels.html

 7
Author: amihaiemil, 2017-07-14 10:32:01

D'après l'exemple de code ci-dessus, il semble que vous ne créiez pas une requête canonique et que vous l'incluiez dans la chaîne qui est signée selon http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html

Au lieu de l'implémenter vous-même, avez-vous envisagé d'utiliser une bibliothèque tierce.

Aws-v4-signer-java est une bibliothèque légère sans dépendance qui facilite la génération de signatures 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();

Avertissement: Je suis les bibliothèques de l'auteur.

 2
Author: lucasweb, 2016-07-16 07:10:05