2016-08-15 10 views
0

Я составляю предварительно подписанный URL-адрес для загрузки объектов из AWS S3. Я использую метод generatePresignedUrl из AWS Java SDK. Тем не менее, я получаю SignatureDoesNotMatch из AWS при создании запроса GET с использованием сгенерированного предварительно подписанного URL. Я смущен, потому что я использую метод из официального SDK для его создания и очень простой запрос GET, но не повезло. Любая помощь очень ценится!Почему AWS не доверяет предварительно подписанным URL-адресам, сгенерированным собственным SDK

Код (взяты из AWS docs):

java.util.Date expiration = new java.util.Date(); 
long milliSeconds = expiration.getTime(); 
milliSeconds += 1000 * 60 * 60; // Add 1 hour. 
expiration.setTime(milliSeconds); 

GeneratePresignedUrlRequest generatePresignedUrlRequest = 
new GeneratePresignedUrlRequest(bucketName, objectKey); 
generatePresignedUrlRequest.setMethod(HttpMethod.GET); 
generatePresignedUrlRequest.setExpiration(expiration); 

URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest); 

учетные данные, которые я использую для подключения к AWS S3 испытаны; Я смог загрузить объекты S3 с использованием тех же учетных данных и метода загрузки S3 из AWS SDK. Но ответ я получаю от АМС к составленному URL (например, https://ozland.s3.amazonaws.com/1865b563cdc94fa28ef41ee0b9b0e608?AWSAccessKeyId=...AWSAccessKeyId...&Expires=1471300223&Signature=pbgcRB0Zg%2B3iicDQQbVX%2FqdNAAc%3D) из выше:

<?xml version="1.0" encoding="UTF-8"?> 
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message 
<AWSAccessKeyId>...AWSAccessKeyId...</AWSAccessKeyId> 
<StringToSign>GET 


1471300223 
/ozland/1865b563cdc94fa28ef41ee0b9b0e608</StringToSign> 
<SignatureProvided>pbgcRB0Zg+3iicDQQbVX/qdNAAc=</SignatureProvided> 
<StringToSignBytes>47 45 54 0a 0a 0a 31 34 37 31 33 30 30 32 32 33 0a 2f 61 6c 61 62 61 6d 61 63 6f 75 6e 74 79 2f 31 38 36 35 62 35 36 33 63 64 65 39 34 66 61 32 38 65 66 34 31 65 65 30 63 39 62 30 65 36 30 38</StringToSignBytes> 
<RequestId>...RequestId...</RequestId> 
<HostId>...HostId...</HostId></Error> 

Возникает вопрос: почему response.StringToSign сверху отличается от того, как AWS документы (AWS docs) описывают Это. В частности, согласно документации, я ожидаю StringToSign быть как:

AWS4-HMAC-SHA256 
20150830T123600Z 
20150830/us-east-1/iam/aws4_request 
f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59 

aws-tools работает просто отлично для меня для создания предварительно подписанных URL, используя тот же S3 ведро и учетные данные. Но почему я все равно получаю SignatureDoesNotMatch?

Спасибо!

ответ

2

Разница заключается в том, что строка для входа в ответ об ошибке находится в формате Signature Version 2, а это, в свою очередь, связано с тем, что ваш подписанный URL-адрес находится в формате V2.

Среди заметных визуальных различий между двумя форматами V2 имеет Signature=[base64], а V4 - X-Amz-Signature=[hex].

Это объясняет разницу между строками.

Он не получает вас ближе к объяснению, почему подпись не совпадает, потому что V2 отлично действует в регионах, начатых до 2014

Наиболее вероятным виновником является обычно недостающий символ или копировать/вставлять ошибку в секретный код или любой пользовательский агент, который вы используете, чтобы сделать запрос, сделать какой-то забавный бизнес. Если строка для подписи совпадает с запросом, который вы делаете, - и похоже, что это так - в V2 не так много, что может быть неправильным, если ваши ключи названы с использованием символов в подмножестве ASCII, который не требует urlencoding - - как представляется, этот запрос. (Допустимыми символами в ключах являются UTF-8, но алфавитно-цифровой ASCII довольно хорошо универсален для всех пользовательских агентов).

+0

Спасибо за ответ. Я дважды проверял учетные данные, они кажутся правильными; Я поменял один символ в тайне, и подключение к AWS теперь не срабатывает, поэтому я уверен, что ключ и секрет верны. – taydakov

+0

Любопытно, что AWS SDK начал возвращать предварительно подписанный URL v4, как только я добавил еще две строки с «s3client.getBucketLocation» и «s3client.getObjectMetadata», которые возвращают правильные данные из S3. Теперь URL-адрес выглядит так: «https://ozland.s3-us-west-2.amazonaws.com/16aff6c1d9744842af9dfa1c2e742254?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20160815T234115Z&X-Amz-SignedHeaders=host&X- Amz-Истекает = 3599 & X-Amz-Credential = ... AWS_KEY ...% 2F20160815% 2Fus-запад 2% 2Fs3% 2Faws4_request & X-Amz-Signature = 8082a9ca5107fd7c4d2422bc3a581f8f15b05e03e50c1a395c09169408ed6476" . Но AWS по-прежнему НЕ принимает его :( – taydakov

+0

Я подозреваю, что ошибка в AWS SDK (моя версия 1.11.26), потому что все остальное работает очень хорошо: учетные данные, подключение к S3, предварительная подпись URL-адресов с использованием сторонних инструментов aws-tools с одинаковыми учетными данными. Сегодня я попробую более старую версию AWS SDK. – taydakov