ChatGPT解决这个技术问题 Extra ChatGPT

Amazon S3 - 如何修复“我们计算的请求签名与签名不匹配”错误?

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

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

我正在尝试使用以下代码连接到我的 Amazon 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 文件如下:

return [
    // Bootstrap the configuration file with AWS specific features
    'includes' => ['_aws'],
    'services' => [
        // 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' => [
            'params' => [
                'credentials' => [
                    'key'    => 'key',
                    'secret' => 'secret'
                ]
            ]
        ]
    ]
];

它产生以下错误:

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

我已经检查了我的访问密钥和秘密至少 20 次,生成了新的,使用不同的方法来传递信息(即配置文件并在代码中包含凭据),但目前没有任何工作。

因此,AWS SDK 只是实现了一堆直接的 API 调用。使用 AWS,您进行的每一次调用都会使用您的私钥(或上面的 secret),并使用它来根据您的访问密钥、当前时间戳以及许多其他因素来计算签名。请参阅docs.aws.amazon.com/general/latest/gr/…。这是一个远景,但考虑到它们包括时间戳,也许您本地环境的时间已经关闭?
当我们在对象元数据中传递了不正确的大小 (Content-Length) 时发生。 (长版:我们直接将输入流从 Java HttpServletRequest 传递到 S3 客户端,并通过元数据将 request.getContentLength() 作为 Content-Length 传递;当 servlet(随机)接收分块请求时(Transfer-Encoding: chunked) , getContentLength() 返回 -1 - 这导致 putObject 失败(随机)。晦涩难懂;但显然是我们的错,因为我们传递了不正确的对象大小。)
第一次访问,请浏览很多答案,在很多情况下您会收到此错误以及此页面中提供的各种解决方案
就我而言,对于 opensearch,我在路径和 URL 中给出了不同的信息......

Y
Yves M.

调试了两天,终于发现问题了……

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

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


前导斜线也为我造成了这个问题。你只需要路径/到/文件,而不是/路径/到/文件
对我来说,问题是键内的空白
除此之外,当我的密钥中有一个加号 + 时,我收到了此错误消息。
在我的情况下,这是由于 bucket 参数中有一个路径引起的。我有 bucket = "bucketname/something" 而不是 bucket = "bucketname"。这也给出了签名不匹配错误。
当我没有在上传文件请求中提供 Content-Type 标头时,我得到了这个
A
Alex Levine

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


我只是双击 key_hash_lala/key_hash_continues,它只选择了一个部分。唉,告诉用户“密码错误,伙计!”有多难?
我第一次从可下载的 csv 复制密钥时遇到问题。对于我创建的第二个密钥,我只是从浏览器中复制了它,没有任何问题
+1 到 @nthaxis - 从 .csv 复制导致失败 - 直接从浏览器复制,效果很好
对我来说,这也是错误凭据的结果。我错过了我的凭据中的一个字符。
对于我们所有使用双击选择和复制的人,它不会复制尾随的“+”字符!
e
ecdeveloper

尝试复制带有一些 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);

通过使用 encodeURIComponent() 对 CopySource 进行编码来解决


谢谢,和我一起工作!我还尝试对“密钥”进行编码,因为密钥还包含 UTF8 字符,并且它最终位于错误的目录中。只有对 CopySource 进行编码才能正常工作。
O
Oleg

我在nodejs中遇到了同样的错误。但是在 s3 构造函数中添加 signatureVersion 帮助了我:

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

在我偶然发现这个之前尝试了很多东西!这就是我的答案。
为我工作,文件路径正常,其他一切正常,目前其他应用程序正在使用相同的功能,并且永远不会在该应用程序中出现此错误。谢谢, 奥列格
这也为我解决了。
H
Harrish Selvarajah

如果您的密钥之前或之后有空格,则似乎主要发生此错误


有同样的问题。 Skype 有时会复制带有空行的值。只需将其粘贴到记事本中,然后将其复制而不使用空格。
是的 !还要检查您在任何其他标题中是否有空格。
A
AliS

我的 AccessKey 中有一些特殊字符没有正确转义。

当我复制/粘贴键时,我没有检查特殊字符。让我绊倒了几分钟。

一个简单的反斜杠修复了它。示例(显然不是我真正的访问密钥):

secretAccessKey: 'Gk/JCK77STMU6VWGrVYa1rmZiq+Mn98OdpJRNV614tM'

变成

secretAccessKey: 'Gk\/JCK77STMU6VWGrVYa1rmZiq\+Mn98OdpJRNV614tM'


s
saurav sarkar

对于 Python 集 - signature_version s3v4

s3 = boto3.client(
   's3',
   aws_access_key_id='AKIAIO5FODNN7EXAMPLE',
   aws_secret_access_key='ABCDEF+c2L7yXeGvUyrPgYsDnWRRC1AYEXAMPLE',
   config=Config(signature_version='s3v4')
)

s
sarir

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


如果您在元数据中传递了不正确的 Content-Length,也会发生这种情况
E
Elon Zito

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


长时间后救了我。谢谢!!
谢谢!我使用的是 POST 而不是 PUT ...使用 PUT 就可以了。
A
Aaron St. Clair

在 aws-php-sdk 的先前版本中,在弃用 S3Client::factory() 方法之前,您可以将文件路径的一部分或 Key(在 S3Client->putObject() parameters 中调用它)放在桶参数。我在生产中使用了一个文件管理器,使用 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 收到的确切消息后,我发现:

https://s3.amazonaws.com/awesomecatpictures%2Fcatsinhats/whitecats/white_cat_in_hat1.png 上执行 PutObject 时出错

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

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

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

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

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


感谢您发布此内容,当我看到“检查您的密钥”时,我认为访问密钥或密钥是错误的。在我的情况下,它是对象键(和存储桶)。因此,按照您的描述移动存储桶和对象键值是可行的。亚马逊需要澄清他们抱怨 IMO 的关键。再次感谢
S
Saurav Panthee

我遇到了同样的问题,我遇到的问题是我导入了错误的环境变量,这意味着我的 AWS 密钥是错误的。在阅读所有答案的基础上,我将验证您的所有访问 ID 和密钥是否正确,并且没有其他字符或任何内容。


E
Emmanuel

对我来说,我使用 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)

同样,更改 content-type 就可以了。
s
saurabh

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

aws configure

this command 将打开一组选项,询问键、区域和输出格式。

希望这可以帮助!


S
Sebastian

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

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

我遇到了这个问题,您的建议解决了它!谢谢@塞巴斯蒂安
A
AVIDeveloper

在我的例子中,我将一个 S3 url 解析为它的组件。

例如:

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

被解析成:

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

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


m
maheeka

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


这对我有用。用于生成签名 URL 的 HTTP 动词(PUT、POST)必须与使用该 URL 执行上传时使用的动词相同。
S
Satish Patro

当我明知地给出了具有“秘密”价值的错误密钥时,它给出了这个错误。我期待一些有效的错误消息详细信息,例如“身份验证失败”或其他内容


J
John Veldboom

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

删除该参数“修复”了问题。


j
jazeb007

在调试并花费大量时间之后,就我而言,问题出在 access_key_id 和 secret_access_key 上,只需仔细检查您的凭据或在可能的情况下生成新的凭据,并确保您在 params 中传递凭据。


当我阅读上面的答案时,我仔细检查了我的密钥并意识到我在最后添加了 / 。
y
yungBolo

生成一个新的访问密钥对我有用。


新的访问密钥也对我有用 - 谢天谢地,我从阅读 github.com/aws/aws-sdk-js/issues/86#issuecomment-153433220 中得到了提示,就我而言,是 SQS 在标题中引发了异常。我之前使用的密钥(出现异常时)是 97 天前,IAM 仪表板中有感叹号
A
Amol Kakade

大多数情况下,它是由于错误的密钥 (AWS_SECRET_ACCESS_KEY) 而发生的。请交叉验证您的 AWS_SECRET_ACCESS_KEY。希望它会工作...


M
Manish Bansal

像其他人一样,我也有类似的问题,但在 java sdk v1.1 中。对我来说,以下 2 个修复对我有帮助。

我的对象键看起来像这样 /path/to/obj/。在此,我首先删除了开头的 /。此外,仅第 1 点并不能解决问题。我将我的 sdk 版本从 1.9.x 升级到 1.11.x

应用这两个修复程序后,它起作用了。所以我的建议不是坚持下去。如果没有其他工作,只需尝试升级 lib。


J
Joseph Combs

我遇到了类似的错误,但对我来说,这似乎是由于重新使用 IAM 用户在两个不同的 Elastic Beanstalk 环境中使用 S3 造成的。我通过为每个环境创建一个具有相同权限的 IAM 用户来治疗这种症状,这使错误消失了。


p
pr1nc3

我不知道是否有人在尝试在浏览器中测试输出的 URL 时遇到此问题,但如果您使用 Postman 并尝试从 RAW 选项卡复制 AWS 生成的 url,因为转义反斜杠您是会得到上述错误。

使用 Pretty 选项卡复制并粘贴 URL 以查看它是否真的有效。

我最近遇到了这个问题,这个解决方案解决了我的问题。这是为了测试目的,看看您是否真的通过 url 检索数据。

此答案是对那些尝试从 AWS 生成下载、临时链接或通常从 AWS 生成 URL 以供使用的人的参考。


你能告诉我你是如何解决这个问题的吗?它在邮递员中工作正常,但在 nodejs 中却不行
J
Juan Sánchez

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


能否请您添加更多详细信息在哪里投放 AWS Sign ?
f
flyingfishcattle

这个问题发生在我身上,因为我不小心将 ACCESS_KEY_ID 的值分配给了 SECRET_ACCESS_KEY_ID。一旦这个问题得到解决,一切正常。


R
Ross Coundon

我刚刚遇到这个,我有点不好意思说,这是因为我使用的是 HTTP POST 请求而不是 PUT。

尽管我很尴尬,但我想我会分享,以防它可以节省一个小时的时间。


j
jcm

我在使用 SDK 的共享环境中遇到了这个错误,但是使用相同的密钥/秘密和 aws cli,它工作正常。构建系统脚本在密钥、秘密和会话密钥之后有一个空格,代码也读入了这些空格。所以对我来说,解决方法是调整构建脚本以在使用变量后删除空格。

只是为那些可能会在他们的信用末尾错过那个令人沮丧的隐形空间的人添加这个。


M
Martin Flower

在我的例子中,bucketname 是错误的,它包含了密钥的第一部分(bucketxxx/keyxxx)——签名没有任何问题。


N
Nir Soudry

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

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅