AWS S3 - Как исправить ошибку «Рассчитанная нами подпись запроса не соответствует подписи»?


89

Я искал в Интернете более двух дней и, вероятно, просмотрел большинство задокументированных в Интернете сценариев и обходных путей, но пока у меня ничего не работало.

Я использую AWS SDK для PHP V2.8.7, работающего на PHP 5.3.

Я пытаюсь подключиться к своей корзине S3 с помощью следующего кода:

// Create a `Aws` object using a configuration file

        $aws = Aws::factory('config.php');

        // Get the client from the service locator by namespace
        $s3Client = $aws->get('s3');

        $bucket = "xxx";
        $keyname = "xxx";

        try {
            $result = $s3Client->putObject(array(
                'Bucket'        =>      $bucket,
                'Key'           =>      $keyname,
                'Body'          =>      'Hello World!'
            ));
            $file_error = false;
        } catch (Exception $e) {
            $file_error = true;
            echo $e->getMessage();
            die();
        }
        //  

Мой файл config.php выглядит следующим образом:

<?php

return array(
    // Bootstrap the configuration file with AWS specific features
    'includes' => array('_aws'),
    'services' => array(
        // All AWS clients extend from 'default_settings'. Here we are
        // overriding 'default_settings' with our default credentials and
        // providing a default region setting.
        'default_settings' => array(
            'params' => array(
                'credentials' => array(
                    'key'    => 'key',
                    'secret' => 'secret'
                )
            )
        )
    )
);

Выдает следующую ошибку:

Подпись запроса, которую мы рассчитали, не соответствует предоставленной вами подписи. Проверьте свой ключ и метод подписи.

Я уже проверил свой ключ доступа и секрет не менее 20 раз, создал новые, использовал разные методы для передачи информации (например, профиль и включение учетных данных в код), но в данный момент ничего не работает.


3
Итак, AWS SDK просто реализует набор прямых вызовов API. В AWS каждый вызов, который вы делаете, берет ваш закрытый ключ (или более secretвысокий) и использует его для вычисления подписи на основе вашего ключа доступа, текущей временной метки и множества других факторов. См. Docs.aws.amazon.com/general/latest/gr/… . Это маловероятно, но, учитывая, что они включают метку времени, возможно, время в вашей локальной среде отключено?
Джош Падник

Произошло, когда мы передали неверный размер ( Content-Length) в метаданных объекта. (Длинная версия: мы напрямую передавали входной поток от Java HttpServletRequestк клиенту S3 и передавали его request.getContentLength()как Content-Lengthчерез метаданные; когда сервлет (случайным образом) получал фрагментированные запросы ( Transfer-Encoding: chunked), getContentLength()возвращался, -1что приводило putObjectк сбою (случайным образом). Непонятно; но явно наша вина, потому что мы пропускали объект неправильного размера.)
Джанака Бандара,

Джош, время моего ноутбука было на час позже (по какой-то причине было установлено московское, а не лондонское время). Спасибо вам за помощь!
Росс Саймондс,

Ответы:


79

После двух дней отладки я наконец обнаружил проблему ...

Ключ, который я назначал объекту, начинался с точки, то есть ..\images\ABC.jpg, и это привело к возникновению ошибки.

Я хочу, чтобы API предоставлял более содержательные и актуальные сообщения об ошибках, но, увы, я надеюсь, что это поможет кому-то еще!


У меня был сегмент состояния и ключ назад, и это ошибка, которую вы получаете (подпись не совпадает). Wtf terraform?
Lo-Tan

14
Передняя косая черта также вызвала у меня эту проблему. Вам нужен только путь / к / файлу, а не / путь / к / файлу
Грэм

3
И для меня вопрос были белые пространства внутри от ключа
Адам Szmyd

3
Чтобы добавить к этому, я получал это сообщение об ошибке, когда +в моем ключе был знак плюса .
LCC

1
Я получал это, когда не Content-Type
указывал

33

Я получаю эту ошибку из-за неправильных учетных данных. Я думаю, что изначально были невидимые символы.


3
Я просто щелкнул двойным щелчком, key_hash_lala/key_hash_continuesи он выбрал только одну часть. Увы, как сложно сказать пользователю «неправильный пароль, чувак!»?
Ufos

В первый раз у меня возникли проблемы с копированием ключа из загружаемого csv. Для второго ключа, который я создал, я просто скопировал его из браузера, и у меня не было никаких проблем
nthaxis

+1 к @nthaxis - копирование из .csv привело к сбою - копирование прямо из браузера, и это работает
NKCampbell

13

У меня была такая же проблема при попытке скопировать объект с некоторыми символами UTF8. Ниже приведен пример JS:

var s3 = new AWS.S3();

s3.copyObject({
    Bucket: 'somebucket',
    CopySource: 'path/to/Weird_file_name_ðÓpíu.jpg',
    Key: 'destination/key.jpg',
    ACL: 'authenticated-read'
}, cb);

Решено путем кодирования CopySource с помощью encodeURIComponent()


9

Эта ошибка чаще всего возникает, если перед или после секретного ключа есть пробел.


это полная помощь
Mr S Coder

Была такая же проблема. Skype иногда копирует значения с пустыми строками. Просто вставьте его в блокнот, а затем скопируйте без пробелов.
michal-michalak

Да ! Также проверьте, есть ли у вас пробелы в других заголовках.
Эйно Гурден,

6

На самом деле в Java я получал ту же ошибку. Потратив 4 часа на ее отладку, я обнаружил, что проблема заключалась в метаданных в объектах S3, поскольку было место при размещении элементов управления кешем в файлах s3. Это пространство было разрешено в 1.6. * версия, но в 1.11. * он запрещен и, следовательно, выдает ошибку несоответствия подписи


Также происходит, если вы передаете неверные Content-Lengthметаданные
Джанака Бандара

3

Если ни одно из других упомянутых решений не работает для вас, попробуйте использовать

aws configure

эта команда откроет набор параметров с запросом ключей, региона и формата вывода.

Надеюсь это поможет!


3

Для меня я использовал аксиомы и глухим отправляет заголовок

content-type: application/x-www-form-urlencoded

поэтому я перехожу на отправку:

content-type: application/octet-stream

а также должен был добавить этот Content-Type в подпись AWS

const params = {
    Bucket: bucket,
    Key: key,
    Expires: expires,
    ContentType = 'application/octet-stream'
}

const s3 = new AWS.S3()
s3.getSignedUrl('putObject', params)

3

В предыдущей версии aws-php-sdk до прекращения поддержки этого S3Client::factory()метода вам было разрешено указывать часть пути к файлу или, Keyкак это называется в S3Client->putObject()параметрах , в параметре корзины. У меня был файловый менеджер в производстве, использующий v2 SDK. Поскольку заводской метод все еще работал, я не возвращался к этому модулю после обновления до ~3.70.0. Сегодня я потратил большую часть двух часов на отладку, почему я начал получать эту ошибку, и в конечном итоге это произошло из-за параметров, которые я передавал (которые раньше работали):

$s3Client = new S3Client([
    'profile' => 'default',
    'region' => 'us-east-1',
    'version' => '2006-03-01'
]);
$result = $s3Client->putObject([
    'Bucket' => 'awesomecatpictures/catsinhats',
    'Key' => 'whitecats/white_cat_in_hat1.png',
    'SourceFile' => '/tmp/asdf1234'
]);

Мне пришлось переместить catsinhatsчасть моего пути ведра / ключа к Keyпараметру, например:

$s3Client = new S3Client([
    'profile' => 'default',
    'region' => 'us-east-1',
    'version' => '2006-03-01'
]);
$result = $s3Client->putObject([
    'Bucket' => 'awesomecatpictures',
    'Key' => 'catsinhats/whitecats/white_cat_in_hat1.png',
    'SourceFile' => '/tmp/asdf1234'
]);

Я считаю, что происходит то, что Bucket имя теперь кодируется URL-адресом. После дальнейшего изучения точного сообщения, которое я получал от SDK, я обнаружил следующее:

Ошибка выполнения PutObjectнаhttps://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.png

Ошибка HTTP AWS: ошибка клиента: PUT https://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.pngпривела к403 Forbidden

Это показывает, что параметр, который /я предоставил для своего Bucketпараметра, был выполнен urlencode()и сейчас %2F.

Подпись работает довольно сложно, но проблема сводится к ведру, и ключ используется для генерации зашифрованной подписи. Если они не совпадают в точности ни на вызывающем клиенте, ни в AWS, запрос будет отклонен с кодом 403. Сообщение об ошибке действительно указывает на проблему:

Подпись запроса, которую мы рассчитали, не соответствует предоставленной вами подписи. Проверьте свой ключ и метод подписи.

Итак, я Keyбыл неправ, потому что Bucketбыл неправ.


3

У меня была такая же ошибка в nodejs. Но signatureVersionмне помогло добавление в конструктор s3:

const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  signatureVersion: 'v4',
});

Пробовал много чего, прежде чем наткнулся на это! Это был ответ для меня.
DavidG

2

Я только что испытал эту загрузку изображения на S3 с помощью AWS SDK с React Native. Оказалось, что это вызваноContentEncoding параметром.

Удаление этого параметра «устранило» проблему.


2

Я была такая же проблема. У меня был метод по умолчанию, PUT, установленный для определения предварительно подписанного URL-адреса, но я пытался выполнить GET. Ошибка возникла из-за несоответствия метода.


Это сработало для меня. Глагол HTTP (PUT, POST), используемый для создания подписанного URL-адреса, должен совпадать с глаголом, используемым при выполнении загрузки с этим URL-адресом.
Craigcaulfield

2

В моем случае я использовал, s3.getSignedUrl('getObject')когда мне нужно было использовать s3.getSignedUrl('putObject')(потому что я использую PUT для загрузки моего файла), поэтому подписи не совпадают.


Спас меня после долгих часов. Спасибо!!
Кисинга

1

У меня была аналогичная ошибка, но мне показалось, что она была вызвана повторным использованием пользователя IAM для работы с S3 в двух разных средах Elastic Beanstalk. Я устранил этот симптом, создав пользователя IAM с одинаковыми правами доступа для каждой среды, и это устранило ошибку.


1

В моем случае я разобрал URL-адрес S3 на его компоненты.

Например:

Url:    s3://bucket-name/path/to/file

Был разобран на:

Bucket: bucket-name
Path:   /path/to/file

Если часть пути содержит начальный символ '/', запрос не выполнен.


1

Другая возможная проблема может заключаться в том, что мета-значения содержат символы, отличные от US-ASCII. Мне помогло UrlEncode значения при добавлении их в putRequest:

request.Metadata.Add(AmzMetaPrefix + "artist", HttpUtility.UrlEncode(song.Artist));
request.Metadata.Add(AmzMetaPrefix + "title", HttpUtility.UrlEncode(song.Title));

1

Я решил эту проблему, изменив публичные разрешения для моей корзины AWS s3 и добавив конфигурацию CORS, указанную ниже, в настройки моей корзины.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration>
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

Дополнительную информацию см. В документации AWS s3 .


1

В большинстве случаев это происходит из-за неправильного ключа (AWS_SECRET_ACCESS_KEY). Перекрестно подтвердите свой AWS_SECRET_ACCESS_KEY. Надеюсь, это сработает ...


1

Я получил эту ошибку при попытке скопировать объект. Я исправил это, закодировав copySource. Это фактически описано в документации метода:

Params: copySource - Имя исходного сегмента и имя ключа исходного объекта, разделенные косой чертой (/). Должен быть закодирован в URL.

CopyObjectRequest objectRequest = CopyObjectRequest.builder()
                .copySource(URLEncoder.encode(bucket + "/" + oldFileKey, "UTF-8"))
                .destinationBucket(bucket)
                .destinationKey(newFileKey)
                .build();

1

В моем случае я использовал S3 (верхний регистр) в качестве имени службы при выполнении запроса с использованием почтальона в методе авторизации подписи AWS.


не могли бы вы добавить более подробную информацию о том, где разместить объявление AWS Sign?
Mr S Coder,

1

После отладки и потраченного много времени, в моем случае проблема была в access_key_id и secret_access_key, просто дважды проверьте свои учетные данные или сгенерируйте новые, если это возможно, и убедитесь, что вы передаете учетные данные в params.


Когда я прочитал ответ выше, я дважды проверил свой секретный ключ и понял, что добавил / в конце.
Ezrqn Kemboi,


0

В моем случае имя ведра было неправильным, оно включало первую часть ключа (bucketxxx / keyxxx) - с подписью все в порядке.


0

В моем случае (python) это не удалось, потому что у меня были эти две строки кода в файле, унаследованные от более старого кода

http.client.HTTPConnection._http_vsn = 10 http.client.HTTPConnection._http_vsn_str = 'HTTP/1.0'


0

Я столкнулся с этим в образе Docker с конечной точкой, отличной от AWS S3, при использовании последней версии awscli версии, доступной для Debian stretch, то есть версии 1.11.13.

Обновление до версии 1.16.84 CLI устранило проблему.

Чтобы установить последнюю версию интерфейса командной строки с файлом Dockerfile на основе растянутого образа Debian, вместо:

RUN apt-get update
RUN apt-get install -y awscli
RUN aws --version

Использование:

RUN apt-get update
RUN apt-get install -y python-pip
RUN pip install awscli
RUN aws --version

0

Мне пришлось установить

Aws.config.update({
  credentials: Aws::Credentials.new(access_key_id, secret_access_key)
})

раньше с ruby ​​aws sdk v2 (вероятно, есть что-то похожее на это и на других языках)


0

Я не знаю, приходил ли кто-нибудь к этой проблеме при попытке протестировать выведенный URL-адрес в браузере, но если вы используете Postmanи пытаетесь скопировать сгенерированный URL-адрес AWS со RAWвкладки, из-за экранирования обратной косой черты вы получите указанную выше ошибку .

Использовать Pretty вкладку, чтобы скопировать и вставить URL-адрес, чтобы проверить, действительно ли он работает.

Недавно я столкнулся с этой проблемой, и это решение решило мою проблему. Это сделано в целях тестирования, чтобы увидеть, действительно ли вы получаете данные через URL-адрес.

Этот ответ является ссылкой на тех, кто пытается сгенерировать загрузку, временную ссылку из AWS или обычно создает URL-адрес из AWS для использования.


0

В моем случае проблема заключалась в URL-адресе шлюза API, который использовался для настройки Amplify, у которого в конце была дополнительная косая черта ...

Запрошенный URL выглядел так https://....amazonaws.com/myapi//myendpoint. Я удалил лишнюю косую черту в конфиге, и это сработало.

Не самое явное сообщение об ошибке в моей жизни.


0

В моем случае я звонил по s3request.promise().then()ошибке, что приводило к двум выполнению запроса, когда был выполнен только один вызов.

Я имею в виду, что я перебирал 6 объектов, но было сделано 12 запросов (вы можете проверить, войдя в консоль или отладив сеть в браузере)

Поскольку отметка времени для второго, нежелательного запроса не соответствовала сигнатуре первого запроса, который вызвал эту проблему.


0

Получена эта ошибка при загрузке документа в CloudSearch через Java SDK. Проблема возникла из-за специального символа в загружаемом документе. Ошибка «Рассчитанная нами подпись запроса не соответствует предоставленной вами подписи. Проверьте свой секретный ключ доступа AWS и метод подписи». вводит в заблуждение.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.