AWS S3 - Jak naprawić błąd „Podpis żądania, który obliczyliśmy, nie pasuje do podpisu”?

89

Szukałem w Internecie od ponad dwóch dni i prawdopodobnie przejrzałem większość udokumentowanych online scenariuszy i obejść, ale jak dotąd nic nie działało.

Jestem na AWS SDK dla PHP V2.8.7 działającego na PHP 5.3.

Próbuję połączyć się z moim wiadrem S3 za pomocą następującego kodu:

// 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();
        }
        //  

Mój plik config.php jest następujący:

<?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'
                )
            )
        )
    )
);

Powoduje następujący błąd:

Podpis żądania, który obliczyliśmy, nie pasuje do podanego przez Ciebie podpisu. Sprawdź swój klucz i metodę podpisywania.

Sprawdziłem już mój klucz dostępu i sekret co najmniej 20 razy, wygenerowałem nowe, użyłem różnych metod przekazywania informacji (tj. Profilu i umieszczania poświadczeń w kodzie), ale w tej chwili nic nie działa.

Joseph Lam
źródło
3
Tak więc AWS SDK po prostu implementuje kilka bezpośrednich wywołań API. Dzięki AWS każde wykonane połączenie pobiera Twój klucz prywatny (lub secretwyższy) i używa go do obliczenia podpisu na podstawie Twojego klucza dostępu, aktualnego sygnatury czasowej oraz szeregu innych czynników. Zobacz docs.aws.amazon.com/general/latest/gr/… . To długa perspektywa, ale biorąc pod uwagę, że zawierają one sygnaturę czasową, być może czas twojego lokalnego środowiska jest wyłączony?
Josh Padnick
Zdarzyło się, gdy przekazaliśmy nieprawidłowy parametr size ( Content-Length) w metadanych obiektu. (Wersja długa: bezpośrednio przekazywaliśmy strumień wejściowy z Javy HttpServletRequestdo klienta S3 i przekazywaliśmy go request.getContentLength()jako Content-Lengthmetadane; gdy serwlet (losowo) odbierał podzielone żądania ( Transfer-Encoding: chunked), getContentLength()zwracał -1- co prowadziło putObjectdo niepowodzenia (losowo). Niejasne; ale najwyraźniej nasza wina, ponieważ mijaliśmy obiekt o nieprawidłowym rozmiarze)
Janaka Bandara
Josh, mój czas na laptopy był o godzinę wolny (z jakiegoś powodu był ustawiony na czas moskiewski, a nie londyński). Dziękuję za pomoc!
Ross Symonds

Odpowiedzi:

79

Po dwóch dniach debugowania w końcu odkryłem problem ...

Klucz, który przypisałem obiektowi zaczynał się od kropki tj. ..\images\ABC.jpgI to spowodowało wystąpienie błędu.

Chciałbym, żeby API zapewniało bardziej znaczące i odpowiednie komunikaty o błędzie, niestety, mam nadzieję, że pomoże to komuś innemu!

Joseph Lam
źródło
Miałem zasobnik stanu i klucz wstecz i to jest błąd, który otrzymujesz (podpis nie pasuje). WTF terraform?
Lo-Tan
14
Wiodący slash również spowodował ten problem. Potrzebujesz tylko ścieżki / do / pliku, a nie / ścieżki / do / pliku
Graham
3
A dla mnie problemem były białe spacje wewnątrz klucza
Adam Szmyd
3
Aby dodać do tego, otrzymywałem ten komunikat o błędzie, gdy +w kluczu pojawił się znak plus .
LCC
1
Content-Type
Otrzymywałem
33

Otrzymuję ten błąd z niewłaściwymi poświadczeniami. Myślę, że były niewidzialne postacie, kiedy pierwotnie go wklejałem.

Alex Levine
źródło
3
Po prostu dwukrotnie kliknąłem key_hash_lala/key_hash_continuesi wybrałem tylko jedną część. Niestety, jak trudno powiedzieć użytkownikowi „złe hasło, koleś!”?
Ufos
Pierwszy raz miałem problemy z kopiowaniem klucza z pliku csv do pobrania. Dla drugiego klucza, który stworzyłem, po prostu skopiowałem go z przeglądarki i nie miałem żadnych problemów
nthaxis
+1 do @nthaxis - kopiowanie z .csv spowodowało awarię - kopiowanie bezpośrednio z przeglądarki i działa
super
13

Miałem ten sam problem, gdy próbowałem skopiować obiekt z niektórymi znakami UTF8. Poniżej znajduje się przykład 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);

Rozwiązany przez zakodowanie CopySource za pomocą encodeURIComponent()

ecdeveloper
źródło
9

Ten błąd pojawia się głównie wtedy, gdy przed lub po tajnym kluczu jest spacja

Harrish Selvarajah
źródło
to jest pełna pomoc
Mr S Coder
Miałem ten sam problem. Skype czasami kopiuje wartości z pustymi wierszami. Po prostu wklej go do notatnika, a następnie skopiuj bez spacji.
michal-michalak
Tak ! Sprawdź także, czy masz spacje w innych nagłówkach.
Eino Gourdin
6

Właściwie w Javie otrzymywałem ten sam błąd. Po spędzeniu 4 godzin na debugowaniu tego, stwierdziłem, że problem tkwił w metadanych w obiektach S3, ponieważ było miejsce podczas umieszczania kontrolek pamięci podręcznej w plikach s3. To miejsce było dozwolone w 1.6. * wersja, ale w 1.11. * jest niedozwolona i dlatego zgłaszała błąd niezgodności podpisu

sarir
źródło
Dzieje się również, jeśli podasz niepoprawne Content-Lengthmetadane
Janaka Bandara
3

Jeśli żadne z innych wymienionych rozwiązań nie działa dla Ciebie, spróbuj użyć

aws configure

to polecenie otworzy zestaw opcji z pytaniem o klucze, region i format wyjściowy.

Mam nadzieję że to pomoże!

saurabh
źródło
3

U mnie użyłem axios i głucho wysyła nagłówek

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

więc zmieniam, aby wysłać:

content-type: application/octet-stream

a także musiałem dodać ten typ treści do podpisu AWS

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

const s3 = new AWS.S3()
s3.getSignedUrl('putObject', params)
Dawid K.
źródło
3

W poprzedniej wersji aws-php-sdk, przed wycofaniem S3Client::factory()metody, można było umieścić część ścieżki pliku lub, Keyjak to się nazywa w S3Client->putObject()parametrach , na parametrze wiadra. Miałem menedżera plików w środowisku produkcyjnym, używając zestawu SDK v2. Ponieważ metoda fabryczna nadal działała, nie wróciłem do tego modułu po aktualizacji do ~3.70.0. Dzisiaj spędziłem większą część dwóch godzin na debugowaniu, dlaczego zacząłem otrzymywać ten błąd, a skończyło się to na parametrach, które mi przekazałem (które kiedyś działały):

$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'
]);

Musiałem przenieść catsinhatsczęść mojej ścieżki wiadra / klucza do Keyparametru, na przykład:

$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'
]);

Wydaje mi się, że Bucketteraz nazwa jest zakodowana w formacie URL. Po dokładnym sprawdzeniu dokładnej wiadomości, jaką otrzymałem z SDK, znalazłem to:

Błąd podczas wykonywania PutObjectnahttps://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.png

Błąd HTTP AWS: błąd klienta: PUT https://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.pngspowodował plik403 Forbidden

To pokazuje, /że podany Bucketprzeze mnie parametr przeszedł urlencode()i jest teraz %2F.

Sposób działania podpisu jest dość skomplikowany, ale problem sprowadza się do zasobnika, a klucz jest używany do generowania zaszyfrowanego podpisu. Jeśli nie pasują dokładnie zarówno do klienta wywołującego, jak i w ramach AWS, żądanie zostanie odrzucone z błędem 403. Komunikat o błędzie faktycznie wskazuje na problem:

Podpis żądania, który obliczyliśmy, nie pasuje do podanego przez Ciebie podpisu. Sprawdź swój klucz i metodę podpisywania.

Więc Keymyliłem się, ponieważ Bucketmyliłem się.

Aaron St. Clair
źródło
3

Miałem ten sam błąd w nodejs. Ale dodanie signatureVersionkonstruktora s3 pomogło mi:

const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  signatureVersion: 'v4',
});
Oleg
źródło
Próbowałem wielu rzeczy, zanim się na to natknąłem! To była odpowiedź dla mnie.
DavidG
2

Właśnie doświadczyłem tego, przesyłając obraz do S3 przy użyciu AWS SDK z React Native. Okazało się, że jest to spowodowane przezContentEncoding parametrem.

Usunięcie tego parametru „rozwiązało” problem.

John Veldboom
źródło
2

Miałem ten sam problem. Miałem domyślną metodę, PUT ustawioną na zdefiniowanie wstępnie podpisanego adresu URL, ale próbowałem wykonać GET. Błąd wynikał z niedopasowania metody.

maheeka
źródło
To zadziałało dla mnie. Czasownik HTTP (PUT, POST) użyty do wygenerowania podpisanego adresu URL musi być taki sam jak czasownik użyty podczas przesyłania z tym adresem URL.
craigcaulfield
2

W moim przypadku używałem, s3.getSignedUrl('getObject')gdy musiałem używać s3.getSignedUrl('putObject')(ponieważ używam PUT do przesyłania mojego pliku), dlatego podpisy się nie zgadzają.

Elon Zito
źródło
Uratował mnie po długich godzinach. Dziękuję Ci!!
Kisinga
1

Miałem podobny błąd, ale wydawało mi się, że był on spowodowany ponownym wykorzystaniem użytkownika IAM do pracy z S3 w dwóch różnych środowiskach Elastic Beanstalk. Usunąłem ten symptom, tworząc użytkownika IAM z identycznymi uprawnieniami dla każdego środowiska i to spowodowało, że błąd zniknął.

Joseph Combs
źródło
1

W moim przypadku przeanalizowałem adres URL S3 na jego składniki.

Na przykład:

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

Został przetworzony na:

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

Posiadanie części ścieżki zawierającej wiodący znak „/” nie powiodło się.

AVIDeveloper
źródło
1

Innym możliwym problemem może być to, że wartości meta zawierają znaki inne niż US-ASCII. U mnie pomogło to UrlEncode wartości podczas dodawania ich do putRequest:

request.Metadata.Add(AmzMetaPrefix + "artist", HttpUtility.UrlEncode(song.Artist));
request.Metadata.Add(AmzMetaPrefix + "title", HttpUtility.UrlEncode(song.Title));
Sebastian
źródło
1

Rozwiązałem ten problem, zmieniając uprawnienia publiczne w moim zasobniku AWS s3 i dodając poniższą konfigurację CORS do ustawień zasobnika.

<?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>

Zobacz dokumentację AWS s3, aby uzyskać więcej informacji.

LobsterBaz
źródło
1

W większości przypadków dzieje się tak z powodu niewłaściwego klucza (AWS_SECRET_ACCESS_KEY). Zweryfikuj krzyżowo swój AWS_SECRET_ACCESS_KEY. Mam nadzieję, że to zadziała ...

Amol Kakade
źródło
1

Wystąpił ten błąd podczas próby skopiowania obiektu. Naprawiłem to przez zakodowanie copySource. Jest to faktycznie opisane w dokumentacji metody:

Params: copySource - nazwa zasobnika źródłowego i nazwa klucza obiektu źródłowego, oddzielone ukośnikiem (/). Musi być zakodowany w formacie URL.

CopyObjectRequest objectRequest = CopyObjectRequest.builder()
                .copySource(URLEncoder.encode(bucket + "/" + oldFileKey, "UTF-8"))
                .destinationBucket(bucket)
                .destinationKey(newFileKey)
                .build();
Diego Keller
źródło
1

W moim przypadku użyłem S3 (wielkie litery) jako nazwy usługi podczas wysyłania żądania za pomocą listonosza w metodzie autoryzacji podpisu AWS

judasane
źródło
czy możesz dodać więcej szczegółów, gdzie umieścić reklamę AWS Sign?
Pan S Coder,
1

Po debugowaniu i spędzeniu dużo czasu, w moim przypadku problem dotyczył access_key_id i secret_access_key, po prostu dwukrotnie sprawdź swoje poświadczenia lub wygeneruj nowe, jeśli to możliwe, i upewnij się, że przekazujesz poświadczenia w params.

jazeb007
źródło
Kiedy przeczytałem powyższą odpowiedź, dwukrotnie sprawdziłem swój tajny klucz i zdałem sobie sprawę, że dodałem / na końcu.
Ezrqn Kemboi
1

Dla zestawu Python - wersja_sygnatury s3v4

s3 = boto3.client(
   's3',
   aws_access_key_id='AKIAIO5FODNN7EXAMPLE',
   aws_secret_access_key='ABCDEF+c2L7yXeGvUyrPgYsDnWRRC1AYEXAMPLE',
   config=Config(signature_version='s3v4')
)
saurav sarkar
źródło
W rzeczy samej. Więcej informacji tutaj: aws.amazon.com/premiumsupport/knowledge-center/…
Davy
0

W moim przypadku nazwa wiadra była błędna, zawierała pierwszą część klucza (bucketxxx / keyxxx) - z podpisem nie było nic złego.

Martin Flower
źródło
0

W moim przypadku (python) nie udało się, ponieważ miałem te dwie linie kodu w pliku, odziedziczone ze starszego kodu

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

Nir Soudry
źródło
0

Napotkałem to na obrazie Dockera, z punktem końcowym innym niż AWS S3, podczas korzystania z najnowszej wersji awscli wersji dostępnej dla Debiana stretch, tj. Wersji 1.11.13.

Aktualizacja do wersji CLI 1.16.84 rozwiązała problem.

Aby zainstalować najnowszą wersję CLI z plikiem Dockerfile opartym na obrazie stretch Debiana, zamiast:

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

Posługiwać się:

RUN apt-get update
RUN apt-get install -y python-pip
RUN pip install awscli
RUN aws --version
RWD
źródło
0

Musiałem ustawić

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

wcześniej z ruby ​​aws sdk v2 (prawdopodobnie jest coś podobnego do tego w innych językach)

Yo Ludke
źródło
0

Nie wiem, czy ktoś przyszedł do tego problemu, próbując przetestować wyjściowy adres URL w przeglądarce, ale jeśli używasz Postmani próbujesz skopiować wygenerowany adres URL AWS z RAWzakładki, z powodu ucieczki odwrotnego ukośnika otrzymasz powyższy błąd .

Użyj Prettykarty, aby skopiować i wkleić adres URL, aby sprawdzić, czy rzeczywiście działa.

Niedawno napotkałem ten problem i to rozwiązanie rozwiązało mój problem. Służy do celów testowych, aby sprawdzić, czy faktycznie pobierasz dane za pośrednictwem adresu URL.

Ta odpowiedź jest odniesieniem do tych, którzy próbują wygenerować pobieranie, tymczasowy link z AWS lub generalnie generują adres URL z AWS do użycia.

pr1nc3
źródło
0

Problemem w moim przypadku był adres URL API Gateway używany do konfigurowania Amplify, który miał dodatkowy ukośnik na końcu ...

Zapytany adres URL wyglądał jak https://....amazonaws.com/myapi//myendpoint. Usunąłem dodatkowy slash w conf i zadziałało.

Nie jest to najbardziej wyraźny komunikat o błędzie w moim życiu.

7hibault
źródło
0

W moim przypadku dzwoniłem do s3request.promise().then()nierzetelności, co spowodowało dwukrotne wykonanie żądania, gdy wykonano tylko jedną rozmowę.

Chodzi mi o to, że iterowałem przez 6 obiektów, ale zgłoszono 12 żądań (możesz to sprawdzić logując się w konsoli lub debugując sieć w przeglądarce)

Ponieważ sygnatura czasowa drugiego, niechcianego żądania nie zgadza się z oznaczeniem pierwszego, które spowodowało ten problem.

Mauricio Gracia Gutierrez
źródło
0

Wystąpił ten błąd podczas przesyłania dokumentu do CloudSearch za pomocą Java SDK. Problem był spowodowany specjalnym znakiem w przesyłanym dokumencie. Błąd „Podpis żądania, który obliczyliśmy, nie jest zgodny z podanym przez Ciebie. Sprawdź swój tajny klucz dostępu AWS i metodę podpisywania”. jest bardzo myląca.

forsa
źródło
0

wygenerowanie nowego klucza dostępu zadziałało dla mnie.

yungBolo
źródło