AWS S3-如何解决“我们计算出的请求签名与签名不匹配”错误?


89

我已经在网上搜索了两天以上,并且可能已经浏览了大多数在线记录的方案和解决方法,但是到目前为止,对我来说没有任何帮助。

我在运行于PHP 5.3的适用于PHP V2.8.7的AWS开发工具包上。

我正在尝试使用以下代码连接到我的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开发工具包仅实现了一系列直接API调用。使用AWS,您进行的每个调用都将使用您的私钥(或secret更高私钥),并使用该私钥根据您的访问密钥,当前时间戳以及许多其他因素来计算签名。参见docs.aws.amazon.com/general/latest/gr/…。这是一个长镜头,但是考虑到它们包括时间戳,也许您当地环境的时间不对?
2015年

当我们Content-Length在对象元数据中传递了不正确的大小()时发生。(长版本:我们从一个Java输入流直接传递HttpServletRequest到S3客户端,并且在通过request.getContentLength()Content-Length经由元数据;当该servlet为(随机地)接收分块请求(Transfer-Encoding: chunked),getContentLength()是返回-1-而导致putObject失败(随机地)。晦涩;但显然是我们的错,因为我们传递的对象尺寸不正确。)
Janaka Bandara

乔什(Josh)的笔记本电脑时间是一个小时的休假(出于某种原因,该时间设置为莫斯科,而不是伦敦时间)。感谢您的帮助!
Ross Symonds

Answers:


79

经过两天的调试,我终于发现了问题...

我分配给对象的键以句点()开头..\images\ABC.jpg,这导致发生错误。

希望API提供更多有意义的相关错误消息,a,希望这对其他人有所帮助!


我有状态存储区和后退键,这是您收到的错误(签名不匹配)。WTF地形?
罗丹(Lo-Tan)

14
斜线也对我造成了这个问题。您只需要路径/至/文件,而无需/路径/至/文件
Graham

3
对我来说,问题是关键内部的空白
Adam Szmyd

3
除此之外,+在密钥中加号时,我收到此错误消息。
LCC

1
我没有Content-Type在上传文件请求中提供标头时收到了此消息
Angel Venchev

33

我使用错误的凭据收到此错误。我认为最初粘贴时有看不见的字符。


3
我简单地双击鼠标key_hash_lala/key_hash_continues,它只选择了一部分。las,告诉用户“密码错误,伙计!”有多难?
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()



6

实际上在Java中,我遇到了同样的错误。花了4个小时对其进行调试之后,我发现问题出在S3对象中的元数据中,因为在s3文件中放置缓存控件时有空间.1.6中允许使用此空间。*版本,但在1.11。*中是不允许的,因此抛出了签名不匹配错误


如果您Content-Length在元数据中传递了不正确的信息,也会发生这种情况
Janaka Bandara

3

如果没有其他提到的解决方案适合您,请尝试使用

aws configure

该命令将打开一组选项,询问键,区域和输出格式。

希望这可以帮助!


3

对我来说,我使用axios并通过默认发送头

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

在弃用该S3Client::factory()方法之前,在aws-php-sdk的早期版本中,允许您将文件路径的一部分或KeyS3Client->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收到的确切消息后,我发现了这一点:

错误执行PutObjecthttps://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.png

AWS HTTP错误:客户端错误: PUT https://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.png导致403 Forbidden

这表明/我提供给我的Bucket参数已经通过urlencode(),现在是%2F

签名的工作方式相当复杂,但是问题归结为存储桶,并且使用密钥来生成加密的签名。如果它们在调用客户端和AWS上都不完全匹配,则请求将被拒绝403。错误消息确实指出了问题:

我们计算出的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。

所以,我Key错了,因为我Bucket错了。


3

我在nodejs中有同样的错误。但是添加signatureVersions3构造函数可以帮助我:

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

在我偶然发现之前,尝试了很多事情!这就是我的答案。
戴维

2

我刚刚经历了使用带有React Native的AWS开发工具包将图像上传到S3的过程。原来是由ContentEncoding参数引起的。

删除该参数可“解决”该问题。


2

我遇到过同样的问题。我有默认的方法,PUT设置为定义预签名的URL,但是试图执行GET。该错误是由于方法不匹配引起的。


这对我有用。用于生成签名URL的HTTP动词(PUT,POST)必须与使用该URL执行上载时使用的动词相同。
craigcaulfield

2

就我而言,我s3.getSignedUrl('getObject')在需要使用时使用s3.getSignedUrl('putObject')(因为我正在使用PUT上传文件),这就是为什么签名不匹配的原因。


长时间工作后救了我。谢谢!!
克辛加

1

我有一个类似的错误,但对我来说,这似乎是由于在两个不同的Elastic Beanstalk环境中重新使用IAM用户来使用S3引起的。我通过为每个环境创建一个具有相同权限的IAM用户来处理症状,从而使错误消失了。


1

就我而言,我将S3网址解析为其组件。

例如:

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

被解析为:

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

使路径部分包含前导“ /”使请求失败。


1

另一个可能的问题是,元值包含非US-ASCII字符。对我来说,将值添加到putRequest时,有助于对值进行UrlEncode编码:

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

尝试复制对象时出现此错误。我通过编码copySource修复了它。实际上在方法文档中对此进行了描述:

参数:copySource –源存储桶的名称和源对象的键名,以斜杠(/)分隔。必须经过URL编码。

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

1

就我而言,在AWS签名授权方法中使用邮递员发出请求时,我使用S3(大写)作为服务名称


您能否在AWS Sign的何处添加更多详细信息?
S编码器先生

1

经过调试并花费了大量时间后,在我的情况下,问题出在access_key_id和secret_access_key上,请仔细检查您的凭据或生成新的凭据(如果可能),并确保您在参数中传递了凭据。


当我阅读以上答案时,我仔细检查了我的密钥,并意识到我在末尾添加了/。
Ezrqn Kemboi


0

在我的情况下,bucketname是错误的,它包含密钥的第一部分(bucketxxx / keyxxx)-签名没有错。


0

在我的情况下(python),它失败了,因为文件中有这两行代码,它们是从较旧的代码继承而来的

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


0

使用最新版本时,我在具有非AWS S3端点的Docker映像中遇到了此问题 awscliDebian Stretch可用版本(即1.11.13版)问题。

升级到CLI版本1.16.84解决了该问题。

要使用基于Debian拉伸映像的Dockerfile安装最新版本的CLI,而不是:

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并尝试从RAW选项卡,由于转义了反斜杠,您将得到上述错误。

使用 Pretty标签来复制并粘贴网址,以查看其是否确实有效。

我最近遇到了这个问题,这个解决方案解决了我的问题。用于测试目的是查看您是否实际上通过url检索数据。

该答案是对那些尝试从AWS生成下载,临时链接或通常从AWS生成要使用的URL的参考。


0

就我而言,问题是用于配置Amplify的API网关URL的末尾有一个额外的斜线...

查询的网址看起来像https://....amazonaws.com/myapi//myendpoint。我删除了conf中的多余斜杠,它起作用了。

不是我一生中最明确的错误消息。


0

就我而言 s3request.promise().then()不正确,导致仅一次调用完成两次请求的执行。

我的意思是,我正在遍历6个对象,但发出了12个请求(您可以通过登录控制台或在浏览器中调试网络进行检查)

由于第二个不需要的请求的时间戳与第一个请求的签名不匹配,因此产生了此问题。


0

通过Java SDK将文档上传到CloudSearch时遇到此错误。问题是由于要上载的文档中有特殊字符。错误“我们计算出的请求签名与您提供的签名不匹配。请检查您的AWS Secret Access密钥和签名方法。” 非常误导。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.