当前位置: 首页 > 知识库问答 >
问题:

如何从Java在AWS中生成签名

淳于新
2023-03-14

当我从REST客户端调用APIendpoint时,由于涉及Signature而出错。

请求:

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

授权: AWS4-HMAC-SHA256凭据={AWSKEY}/20160314/ap-东南-1/执行-api/aws4_request, SignedHeaders=host;范围;x-amz-日期,签名={签名}

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示例java

共有3个答案

林国安
2023-03-14

这是可能的使用100%java库没有额外的依赖关系,只需使用这里生成的查询参数:

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.Formatter;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

...

private static final String ACCESS_KEY = "...";
private static final String SECRET_KEY = "...";
private static final int expiresTime = 1 * 24 * 60 * 60;
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";

public void sign(String protocol, String bucketName, String contentPath) throws Exception {
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.HOUR_OF_DAY, 24);

    String host = bucketName + ".s3-us-west-2.amazonaws.com";
    long expireTime = cal.getTimeInMillis() / 1000;

    String signString = "GET\n" +
        "\n" +
        "\n" +
        expireTime + "\n" +
        "/" + bucketName + contentPath;

    SecretKeySpec signingKey = new SecretKeySpec(SECRET_KEY.getBytes(), HMAC_SHA1_ALGORITHM);
    Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
    mac.init(signingKey);
    String signature = URLEncoder.encode(new String(Base64.getEncoder().encode(mac.doFinal(signString.getBytes()))));

    System.out.println(signature);
    String fullPayload = "?AWSAccessKeyId=" + ACCESS_KEY +
        "&Expires=" + expireTime + 
        "&Signature=" + signature;

    System.out.println(protocol + "://" + host + contentPath + fullPayload);
}

...
范嘉
2023-03-14

从上面的代码示例来看,您似乎没有创建规范化请求并将其包含在根据签名的字符串中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();

免责声明:我是图书馆的作者。

单展
2023-03-14

可以使用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>());

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

 类似资料:
  • 我需要使用SpringRestTemplate(绑定了一个代理)从AWS SQS获取消息,而不是AWS sdk或SpringCloud AWS消息,因为该公司存在一些代理问题。 我需要生成一个头字符串,其中包括这样的授权签名; 我需要用java生成这个signaturewith并绑定到HttpHeaders对象。 我更喜欢使用rest模板,因为在添加下面这样的代理时使用aws sdk是行不通的。应

  • 我想用pdf摘要签署pdf文件。我使用下面的代码创建了散列, 最后,我需要把这个签名附在我的PDF上。我找到了一个解决方案,从文件摘要创建pkcs7签名,但在链接中使用的算法是SHA256with RSA。我的privatekey是使用EC算法生成的,我需要使用SHA256withECDSA。是否可以使用SHA256withECDSA对哈希进行签名,并使用PDFBox ExternalSignin

  • 我正在开发java web应用程序,现在我正在尝试将我的网站与QTIWorks连接起来 我有一个消费者密钥和秘密,我需要生成OAuth签名通过线性时不变系统与QTIWorks连接 我需要在这行生成OAuth签名 我该怎么做?

  • 问题内容: 我需要在运行时生成自签名证书,对其进行签名并导入到Java密钥库中。我可以通过以下方式从命令行使用“ keytool”和“ openssl”来做到这一点: 当然,我可以使用keytool和openssl二进制文件来交付我的应用程序,并从Java执行上述命令,但是我正在寻找一种更干净的方法,该方法允许我使用纯Java来完成上述所有操作。 我可以使用任何库吗? 问题答案: 使用Bouncy

  • 我按照https://docs.aws.amazon.com/amazons3/latest/dev/shareObjectPresignedurlJavasdk.html中的示例创建预签名的s3 url(v4),当我试图访问签名的url时,会出现Access Denied错误 下面是代码段 签名格式似乎是正确的,我不确定是否遗漏了其他一些s3客户端配置。由于我没有得到签名不匹配错误或无效的url

  • 问题内容: 我想用Java生成一个.torrent文件,但是我不想要一个大的API,它可以执行诸如抓取跟踪器,种子等操作。这仅适用于生成元数据的客户端。存在哪些轻量级解决方案?我只生成一个.zip文件的.torrent。 谢谢! 问题答案: 我整理了这段独立的Java代码,以准备一个带有单个文件的.torrent文件。 通过调用.torrent文件的名称,共享文件的名称和跟踪器URL 来创建.to