如何在Java中使用签名版本4正确签名AWS请求?
我希望向AWS上的Elemental MediaConvert发送一个作业请求,我正在阅读您需要如何专门为您的帐户和区域请求端点,所以我这样做了,现在我有了自定义端点。我完成了向该端点签名请求的过程,如图所示,但我似乎无法通过-如何在Java中使用签名版本4正确签名AWS请求?,java,amazon-web-services,aws-media-convert,Java,Amazon Web Services,Aws Media Convert,我希望向AWS上的Elemental MediaConvert发送一个作业请求,我正在阅读您需要如何专门为您的帐户和区域请求端点,所以我这样做了,现在我有了自定义端点。我完成了向该端点签名请求的过程,如图所示,但我似乎无法通过-403禁止:[{“消息”:“我们计算的请求签名与您提供的签名不匹配…” 以下是我目前拥有的: private String MEDIA_CONVERT_ENDPOINT = "https://abcd1234.mediaconvert.us-east-1.amazonaw
403禁止:[{“消息”:“我们计算的请求签名与您提供的签名不匹配…”
以下是我目前拥有的:
private String MEDIA_CONVERT_ENDPOINT = "https://abcd1234.mediaconvert.us-east-1.amazonaws.com/2017-08-29/jobs";
private String MEDIA_CONVERT_HOST = "abcd1234.mediaconvert.us-east-1.amazon.com";
private String AWS_ACCESS_KEY = "AKIAXXXXXXEXAMPLE";
private String AWS_SECRET_KEY = "2AXXXXXXXXXXXX/XXXXXXXXXXXXXXX";
static byte[] HmacSHA256(String data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
String algorithm = "HmacSHA256";
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
}
static String getSignature(String secretKey, String date, String region, String service, String stringToSign) {
byte[] kSecret, kDate, kRegion, kService, kSigning, signature;
try {
kSecret = ("AWS4" + secretKey).getBytes(StandardCharsets.UTF_8);
kDate = HmacSHA256(date, kSecret);
kRegion = HmacSHA256(region, kDate);
kService = HmacSHA256(service, kRegion);
kSigning = HmacSHA256("aws4_request", kService);
signature = HmacSHA256(stringToSign, kSigning);
} catch (Exception e) {
return "";
}
return DatatypeConverter.printHexBinary(signature).toLowerCase();
}
static String hash(String stringToEncrypt) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA-256");
} catch (Exception e) {
return "";
}
messageDigest.update(stringToEncrypt.getBytes(StandardCharsets.UTF_8));
return DatatypeConverter.printHexBinary(messageDigest.digest()).toLowerCase();
}
private ExecutorService executor = Executors.newFixedThreadPool(5);
public Future<APIResponse> sendJob(String jobString) {
TimeZone tz = TimeZone.getTimeZone("UTC");
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
sdf.setTimeZone(tz);
DateFormat df = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());
StringBuilder canonicalRequestBuilder = new StringBuilder("POST");
canonicalRequestBuilder.append("\n")
.append("/2017-08-29/jobs/").append("\n")
.append("\n")
.append("content-type:application/json").append("\n")
.append("host:").append(MEDIA_CONVERT_HOST).append("\n")
.append("x-amz-content-sha256:").append(hash(jobString)).append("\n")
.append("x-amz-date:").append(nowAsISO).append("\n")
.append("\n")
.append("content-type;host;x-amz-content-sha256;x-amz-date").append("\n")
.append(hash(jobString));
String hashedCanonicalRequest = hash(canonicalRequestBuilder.toString());
StringBuilder stringToSignBuilder = new StringBuilder("AWS4-HMAC-SHA256");
stringToSignBuilder.append("\n")
.append(nowAsISO).append("\n")
.append(sdf.format(date)).append("/us-east-1/mediaconvert/aws4_request").append("\n")
.append(hashedCanonicalRequest);
String signature = getSignature(
"AWS4" + AWS_SECRET_KEY,
sdf.format(date),
"us-east-1",
"mediaconvert",
stringToSignBuilder.toString()
);
Callable<APIResponse> task = () -> {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("X-Amz-Content-Sha256", hash(jobString));
headers.set("X-Amz-Date", nowAsISO);
headers.set(
"Authorization",
"AWS4-HMAC-SHA256 Credential=" +
AWS_ACCESS_KEY +
"/" + sdf.format(date) + "/us-east-1/mediaconvert/aws4_request, " +
"SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=" + signature
);
HttpEntity<String> restRequest = new HttpEntity<>(jobString, headers);
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(20000);
requestFactory.setConnectTimeout(5000);
restTemplate.setRequestFactory(requestFactory);
try {
ResponseEntity<APIResponse> response = restTemplate.exchange(MEDIA_CONVERT_ENDPOINT, HttpMethod.POST, restRequest, APIResponse.class);
return response.getBody();
} catch (Exception e) {
return new APIResponse(APIResponse.STATUS_FAILED, e.getMessage());
}
};
return executor.submit(task);
}
私有字符串媒体\u转换\u端点=”https://abcd1234.mediaconvert.us-east-1.amazonaws.com/2017-08-29/jobs";
私有字符串MEDIA\u CONVERT\u HOST=“abcd1234.mediaconvert.us-east-1.amazon.com”;
私有字符串AWS\u ACCESS\u KEY=“AKIAXXXXXXEXAMPLE”;
私有字符串AWS_SECRET_KEY=“2xxxxxxxxxxx/xxxxxxxxxxxxx”;
静态字节[]HmacSHA256(字符串数据,字节[]键)引发NoSuchAlgorithmException,InvalidKeyException{
字符串算法=“HmacSHA256”;
Mac Mac=Mac.getInstance(算法);
init(新的SecretKeySpec(key,algorithm));
返回mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
}
静态字符串getSignature(字符串secretKey、字符串日期、字符串区域、字符串服务、字符串stringToSign){
字节[]k加密、kDate、kRegion、k服务、k签名、签名;
试一试{
kSecret=(“AWS4”+secretKey).getBytes(StandardCharsets.UTF_8);
kDate=HmacSHA256(日期,k机密);
kRegion=HmacSHA256(区域,kDate);
K服务=HmacSHA256(服务,克里翁);
kSigning=HmacSHA256(“aws4_请求”,kService);
签名=HmacSHA256(stringToSign,kSigning);
}捕获(例外e){
返回“”;
}
返回DatatypeConverter.printHexBinary(signature.toLowerCase();
}
静态字符串哈希(字符串stringToEncrypt){
消息摘要消息摘要;
试一试{
messageDigest=messageDigest.getInstance(“SHA-256”);
}捕获(例外e){
返回“”;
}
update(stringToEncrypt.getBytes(StandardCharsets.UTF_8));
返回DatatypeConverter.printHexBinary(messageDigest.digest()).toLowerCase();
}
私有ExecutorService executor=Executors.newFixedThreadPool(5);
公共未来
连续18个小时都在处理这个问题,但似乎找不到我把签名弄乱的地方。谢谢。您是否尝试过调用AWSMediaConvertClientBuilder.setEndpointConfiguration()
然后让它完成工作?@kdgregory我没有,我们的应用程序中没有使用SDK,这将是我们唯一需要它的东西,所以我尝试只做签名并给自己打电话。谢谢。