AWS S3 - Como corrigir o erro 'A assinatura da solicitação que calculamos não corresponde à assinatura'?


97

Tenho pesquisado na web há mais de dois dias e provavelmente já examinei a maioria dos cenários e soluções alternativas documentados on-line, mas nada funcionou para mim até agora.

Estou no AWS SDK para PHP V2.8.7 em execução no PHP 5.3.

Estou tentando me conectar ao meu intervalo S3 com o seguinte código:

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

Meu arquivo config.php é o seguinte:

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

Ele está produzindo o seguinte erro:

A assinatura da solicitação que calculamos não corresponde à assinatura que você forneceu. Verifique sua chave e método de assinatura.

Já verifiquei minha chave de acesso e segredo pelo menos 20 vezes, gerei novos, usei métodos diferentes para passar as informações (ou seja, perfil e inclusão de credenciais no código), mas nada está funcionando no momento.


3
Portanto, o SDK da AWS apenas implementa várias chamadas de API diretas. Com a AWS, cada chamada que você faz pega sua chave privada (ou secretsuperior) e a usa para calcular uma assinatura com base em sua chave de acesso, o carimbo de data / hora atual, além de vários outros fatores. Consulte docs.aws.amazon.com/general/latest/gr/… . É uma possibilidade remota, mas, considerando que incluem o carimbo de data / hora, talvez o horário do seu ambiente local esteja errado.
Josh Padnick

Aconteceu quando passamos um tamanho incorreto ( Content-Length) nos metadados do objeto. (Versão longa: estávamos passando diretamente o fluxo de entrada de um Java HttpServletRequestpara o cliente S3, e passando request.getContentLength()por Content-Lengthmeio de metadados; quando o servlet estava (aleatoriamente) recebendo solicitações fragmentadas ( Transfer-Encoding: chunked), getContentLength()estava retornando -1- o que levou putObjectà falha (aleatoriamente). Obscuro; mas claramente nossa culpa, porque estávamos passando um tamanho de objeto incorreto.)
Janaka Bandara

Josh, o tempo dos meus laptops estava uma hora atrasado (por algum motivo, estava definido para Moscou e não para Londres). Obrigado pela ajuda!
Ross Symonds,

Respostas:


83

Após dois dias de depuração, finalmente descobri o problema ...

A chave que eu estava atribuindo ao objeto começava com um ponto ..\images\ABC.jpg, isto é , e isso causava o erro.

Desejo que a API forneça mensagens de erro mais significativas e relevantes, infelizmente, espero que isso ajude alguém por aí!


Eu tinha o balde de estado e a chave ao contrário e este é o erro que você obtém (a assinatura não corresponde). Wtf terraform?
Lo-Tan

17
Uma barra à esquerda também causou esse problema para mim. Você precisa apenas do caminho / para / arquivo, não / caminho / para / arquivo
Graham

4
E para mim o problema eram os espaços em branco dentro da chave
Adam Szmyd

4
Para adicionar a isso, eu estava recebendo esta mensagem de erro ao ter um sinal de mais +na minha chave.
LCC

2
Eu estava recebendo isso quando não Content-Type
forneci

38

Recebo este erro com as credenciais erradas. Acho que havia personagens invisíveis quando colei originalmente.


3
Simplesmente cliquei em dobuble key_hash_lala/key_hash_continuese ele selecionou apenas uma parte. Infelizmente, é difícil dizer ao usuário "senha errada, cara!"?
Ufos

A primeira vez que tive problemas ao copiar a chave do csv para download. Para a segunda chave que criei, apenas copiei do navegador e não tive nenhum problema
nthaxis

+1 para @nthaxis - copiar do .csv causou uma falha - copiar diretamente do navegador e funciona muito bem
NKCampbell

Para mim, também foi o resultado de credenciais erradas. Perdi um personagem em minhas credenciais.
Promessa Preston

15

Tive o mesmo problema ao tentar copiar um objeto com alguns caracteres UTF8. Abaixo está um exemplo de 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);

Resolvido ao codificar o CopySource com encodeURIComponent()


12

Este erro parece ocorrer principalmente se houver um espaço antes ou depois da sua chave secreta


isto é ajuda completa
Sr. S Coder

Tive o mesmo problema. Às vezes, o Skype copia valores com linhas em branco. Basta colá-lo no bloco de notas e copiá-lo sem espaços em branco.
michal-michalak

Sim ! Verifique também se você tem espaços em qualquer outro cabeçalho.
Eino Gourdin

6

Na verdade, em Java, eu estava recebendo o mesmo erro. Depois de passar 4 horas para depurá-lo, descobri que o problema estava nos metadados em Objetos S3, pois havia espaço ao sentar os controles de cache em arquivos s3. Esse espaço era permitido em 1.6. * versão, mas em 1.11. * não é permitido e, portanto, estava gerando o erro de incompatibilidade de assinatura


Também acontece se você passar um incorreto Content-Lengthnos metadados
Janaka Bandara

4

Para mim usei axios e por surdo manda cabeçalho

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

então eu mudo para enviar:

content-type: application/octet-stream

e também teve que adicionar este Content-Type à assinatura AWS

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

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

3

Se nenhuma das outras soluções mencionadas funcionar para você, tente usar

aws configure

este comando abrirá um conjunto de opções solicitando chaves, região e formato de saída.

Espero que isto ajude!


3

Em uma versão anterior do aws-php-sdk, antes da depreciação do S3Client::factory()método, você tinha permissão para colocar parte do caminho do arquivo, ou Keycomo é chamado nos S3Client->putObject()parâmetros , no parâmetro bucket. Tive um gerenciador de arquivos em uso em produção, usando o SDK v2. Como o método de fábrica ainda funcionava, não visitei novamente este módulo depois de atualizar para ~3.70.0. Hoje gastei quase duas horas depurando porque comecei a receber esse erro, e acabou sendo devido aos parâmetros que eu estava passando (que funcionavam):

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

Tive que mover a catsinhatsparte do meu caminho de intervalo / chave para o Keyparâmetro, assim:

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

O que eu acredito que está acontecendo é que o Bucket nome agora está sendo codificado por URL. Após uma inspeção mais detalhada da mensagem exata que estava recebendo do SDK, encontrei o seguinte:

Erro ao executar PutObjectemhttps://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.png

Erro HTTP AWS: Erro do cliente: PUT https://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.pngresultou em um403 Forbidden

Isso mostra que o que /eu forneci ao meu Bucketparâmetro já passou urlencode()e agora está %2F.

A maneira como a assinatura funciona é bastante complicada, mas o problema se resume ao intervalo e à chave usados ​​para gerar a assinatura criptografada. Se eles não corresponderem exatamente no cliente de chamada e dentro da AWS, a solicitação será negada com um 403. A mensagem de erro realmente aponta o problema:

A assinatura da solicitação que calculamos não corresponde à assinatura que você forneceu. Verifique sua chave e método de assinatura.

Então, eu Keyestava errado porque eu Bucketestava errado.


3

Eu tive o mesmo erro no nodejs. Mas adicionar o signatureVersionconstrutor s3 me ajudou:

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

Tentei muitas coisas antes de tropeçar nisso! Esta foi a resposta para mim.
DavidG

3

No meu caso, eu estava usando s3.getSignedUrl('getObject')quando precisava usar s3.getSignedUrl('putObject')(porque estou usando um PUT para fazer upload do meu arquivo), por isso as assinaturas não coincidem.


Me salvou depois de muitas horas. Obrigado!!
Kisinga


2

Acabei de fazer o upload de uma imagem para S3 usando o SDK da AWS com React Native. Descobriu-se que era causado peloContentEncoding parâmetro.

A remoção desse parâmetro "corrigiu" o problema.


2

Eu tive o mesmo problema. Eu tinha o método padrão, PUT configurado para definir a URL pré-assinada, mas estava tentando executar um GET. O erro foi devido à incompatibilidade de método.


Isso funcionou para mim. O verbo HTTP (PUT, POST) usado para gerar o URL assinado deve ser o mesmo que o verbo usado ao realizar um upload com esse URL.
craigcaulfield

1

Eu tive um erro semelhante, mas para mim parecia ser causado pela reutilização de um usuário IAM para trabalhar com o S3 em dois ambientes diferentes do Elastic Beanstalk. Tratei o sintoma criando um usuário IAM com permissão idêntica para cada ambiente e isso fez o erro desaparecer.


1

No meu caso, analisei um url S3 em seus componentes.

Por exemplo:

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

Foi analisado em:

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

Ter a parte do caminho contendo um '/' inicial falhou na solicitação.


1

Outro possível problema pode ser que os metavalores contenham caracteres não US-ASCII. Para mim, ajudou a UrlEncode os valores ao adicioná-los ao putRequest:

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

1

Resolvi esse problema alterando as permissões públicas em meu bucket AWS s3 e adicionando a configuração CORS abaixo às configurações de meu bucket.

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

Consulte a documentação do AWS s3 para obter mais informações.


1

Na maioria das vezes, isso acontece por causa da chave errada (AWS_SECRET_ACCESS_KEY). Faça uma verificação cruzada de seu AWS_SECRET_ACCESS_KEY. Espero que funcione ...


1

Recebi este erro ao tentar copiar um objeto. Eu consertei codificando o copySource. Na verdade, isso está descrito na documentação do método:

Params: copySource - O nome do intervalo de origem e o nome da chave do objeto de origem, separados por uma barra (/). Deve ser codificado por URL.

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

1

No meu caso, eu estava usando S3 (maiúsculas) como nome de serviço ao fazer a solicitação usando carteiro no método de autorização de assinatura da AWS


você pode adicionar mais detalhes onde anunciar o Sinal da AWS?
Sr. S Coder

1

Depois de depurar e gastar muito tempo, no meu caso, o problema era com access_key_id e secret_access_key, apenas verifique suas credenciais ou gere uma nova se possível e certifique-se de que está passando as credenciais em params.


Quando li a resposta acima, verifiquei minha chave secreta e percebi que adicionei / no final.
Ezrqn Kemboi

0

No meu caso, o nome do intervalo estava errado, ele incluía a primeira parte da chave (bucketxxx / keyxxx) - não havia nada de errado com a assinatura.


0

No meu caso (python) falhou porque eu tinha essas duas linhas de código no arquivo, herdadas de um código mais antigo

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


0

Eu encontrei isso em uma imagem Docker, com um endpoint não AWS S3, ao usar o mais recente awscli versão recente disponível para extensão do Debian, ou seja, versão 1.11.13.

O upgrade para a versão CLI 1.16.84 resolveu o problema.

Para instalar a versão mais recente da CLI com um Dockerfile baseado em uma imagem esticada do Debian, em vez de:

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

Usar:

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

0

Eu tive que definir

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

antes com o ruby ​​aws sdk v2 (provavelmente há algo semelhante a isso nas outras línguas também)


0

Não sei se alguém teve esse problema ao tentar testar o URL de saída no navegador, mas se você estiver usando Postmane tentar copiar o url gerado do AWS da RAWguia, por causa de barras invertidas de escape, você obterá o erro acima .

Use a Prettyguia para copiar e colar o url para ver se ele realmente funciona.

Encontrei esse problema recentemente e essa solução resolveu o meu problema. É para fins de teste, para ver se você realmente recupera os dados por meio do url.

Esta resposta é uma referência para aqueles que tentam gerar um download, um link temporário da AWS ou geralmente gerar uma URL da AWS para usar.


0

O problema no meu caso era o URL do API Gateway usado para configurar o Amplify que tinha uma barra extra no final ...

O url consultado parecia https://....amazonaws.com/myapi//myendpoint. Eu removi a barra extra no conf e funcionou.

Não é a mensagem de erro mais explícita da minha vida.


0

No meu caso, eu estava chamando s3request.promise().then()incorreclty, o que causou duas execuções da solicitação ocorrendo quando apenas uma chamada foi feita.

O que quero dizer é que eu estava iterando por meio de 6 objetos, mas 12 solicitações foram feitas (você pode verificar fazendo login no console ou depurando rede no navegador)

Como o carimbo de data / hora da segunda solicitação indesejada não correspondia à assinatura da primeira, isso gerou esse problema.


0

Recebi este erro ao fazer o upload do documento para CloudSearch por meio do Java SDK. O problema era devido a um caractere especial no documento a ser carregado. O erro "A assinatura da solicitação que calculamos não corresponde à assinatura que você forneceu. Verifique sua chave de acesso secreta da AWS e o método de assinatura." é muito enganador.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.