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()

ecdeveloper
источник
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

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

AVIDeveloper
источник
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 .

LobsterBaz
источник
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.

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

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

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

Для набора Python - signature_version s3v4

s3 = boto3.client(
   's3',
   aws_access_key_id='AKIAIO5FODNN7EXAMPLE',
   aws_secret_access_key='ABCDEF+c2L7yXeGvUyrPgYsDnWRRC1AYEXAMPLE',
   config=Config(signature_version='s3v4')
)
Саурав Саркар
источник
На самом деле. Более подробная информация здесь: aws.amazon.com/premiumsupport/knowledge-center/…
Дэви,
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 для использования.

pr1nc3
источник
0

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

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

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

7hibault
источник
0

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

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

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

Маурисио Грасиа Гутьеррес
источник
0

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

бабки
источник
0

создание нового ключа доступа сработало для меня.

YungBolo
источник