У нас есть метод POST, представленный на шлюзе API с включенной подписью 4. AWS сигнатура 4 работает нормально, когда в поле «* 1010» нет специальных символов. Но всякий раз, когда в полезной нагрузке JSON есть поле с такими символами, как апостроф ('), кавычки ("), мы получаем следующую ошибку. Имеет ли это какое-то отношение к кодировке?
Рассчитанная нами подпись запроса не соответствует предоставленной вами подписи. Проверьте свой секретный ключ доступа AWS и метод подписи. Для получения подробной информации обратитесь к документации по обслуживанию. \ N \ nСтрока Canonical для этого запроса должна быть \ n'POST \ n
Ниже приведен фрагмент кода
private String calculateStringToSign() {
final String stringToSign = format(STRING_TO_SIGN_FORMAT,
SCHEME,
ALGORITHM,
DATE_HEADER_FORMATTER.format(signingTime),
getScope(),
toHexString(sha256(getCanonicalRequest())));
log.debug("String to sign is ["+stringToSign+"]");
return stringToSign;
}
private String getCanonicalRequest() {
final String canonicalString = format(CANONICAL_REQUEST_FORMAT,
method,
getCanonicalizedResourcePath(),
getCanonicalizedQueryString(),
getCanonicalizedHeaders(),
getCanonicalizedHeaderNames(),
getHashedBody());
log.debug("Canonical String is: ["+canonicalString+"]");
return canonicalString;
}
private String getHashedBody() {
return toHexString(sha256(body)).toLowerCase();
}
public static byte[] sha256(String input) {
return hash(input, "SHA-256");
}
private static byte[] hash(String input, String algorithm) {
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(input.getBytes(UTF_8));
return md.digest();
}
catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
log.error("Unable to compute hash", e);
throw new AWSEncryptionException(e);
}
}
private String getCanonicalizedResourcePath() {
Optional<String> path = ofNullable(url).map(URL::getPath);
if(!path.isPresent() || isBlank(path.get())) {
return "/";
}
String encodedPath = urlEncode(path.get());
if (encodedPath.startsWith("/")) {
return encodedPath;
}
else {
return "/".concat(encodedPath);
}
}
private String urlEncode(String value) {
String encoded;
try {
encoded= URLEncoder.encode(value, UTF_8);
}
catch (UnsupportedEncodingException e) {
log.error("Specified URL encoding is not supported", e);
throw new AWSEncryptionException(e);
}
encoded = encoded.replace("%2F", "/");
encoded = encoded.replace("%7E", "~");
return encoded;
}
private String getCanonicalizedHeaderNames() {
return headers.keySet().stream()
.sorted(CASE_INSENSITIVE_ORDER)
.map(String::toLowerCase)
.collect(joining(";"));
}
private String getCanonicalizedHeaders() {
return headers.keySet().stream()
.sorted(CASE_INSENSITIVE_ORDER)
.map(key -> {
String formattedKey = key.toLowerCase().replaceAll("\\s+", " ");
String formattedValue = headers.get(key).stream()
.filter(Objects::nonNull)
.flatMap(value -> of(value.split("\\R+")))
.map(StringUtils::trimWhitespace)
.map(value -> value.replaceAll("\\s+", " "))
.collect(joining(","));
return formattedKey + ":" + formattedValue;
})
.collect(joining("\n"));
}
private String getCanonicalizedQueryString() {
return queryParameters.entrySet().stream()
.flatMap(entry -> entry.getValue().stream()
.map(value -> new AbstractMap.SimpleEntry<>(
urlEncode(entry.getKey()), urlEncode(value)
))
.collect(toList())
.stream()
)
.map(entry -> entry.getKey() + "=" + entry.getValue())
.sorted()
.collect(joining("&"));
}