178

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

我使用的是在 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 次,生成了新的,使用了不同的方法来传递信息(即配置文件并在代码中包含凭据),但目前没有任何工作。

4

52 回答 52

131

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

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

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

于 2015-05-29T01:37:08.477 回答
55

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

于 2015-09-05T07:04:26.060 回答
25

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

于 2016-04-05T20:31:15.963 回答
19

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

const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  signatureVersion: 'v4',
});
于 2019-07-08T16:20:54.243 回答
18

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

于 2020-06-01T16:59:59.250 回答
8

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

于 2017-02-21T10:33:01.987 回答
8

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

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

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

secretAccessKey: 'Gk/JCK77STMU6VWGrVYa1rmZiq+Mn98OdpJRNV614tM'

变成

secretAccessKey: 'Gk\/JCK77STMU6VWGrVYa1rmZiq\+Mn98OdpJRNV614tM'

于 2020-11-18T20:38:34.830 回答
8

对我来说,我使用 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)
于 2019-02-28T03:05:08.567 回答
8

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

于 2020-02-28T17:45:54.880 回答
7

在 aws-php-sdk 的先前版本中,在弃用该S3Client::factory()方法之前,您可以将文件路径的一部分放置在存储桶参数上,或者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 收到的确切消息后,我发现:

PutObject执行时出错https://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错了。

于 2019-03-04T21:12:01.833 回答
6

对于 Python 集 - signature_version s3v4

s3 = boto3.client(
   's3',
   aws_access_key_id='AKIAIO5FODNN7EXAMPLE',
   aws_secret_access_key='ABCDEF+c2L7yXeGvUyrPgYsDnWRRC1AYEXAMPLE',
   config=Config(signature_version='s3v4')
)
于 2020-09-08T10:05:58.747 回答
6

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

于 2021-01-06T19:57:45.150 回答
5

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

aws configure

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

希望这可以帮助!

于 2018-02-19T06:21:54.270 回答
4

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

于 2021-03-15T14:23:11.720 回答
4

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

例如:

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

被解析成:

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

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

于 2018-11-13T09:44:12.337 回答
4

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

request.Metadata.Add(AmzMetaPrefix + "artist", HttpUtility.UrlEncode(song.Artist));
request.Metadata.Add(AmzMetaPrefix + "title", HttpUtility.UrlEncode(song.Title));
于 2018-12-14T09:16:55.770 回答
3

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

于 2019-05-29T05:41:39.873 回答
3

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

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

于 2018-03-09T18:17:43.253 回答
2

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

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

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

于 2021-06-04T17:43:52.573 回答
2

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

于 2019-08-01T11:22:25.543 回答
2

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

于 2019-11-26T05:25:39.150 回答
1

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

于 2017-06-14T23:55:56.303 回答
1

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

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

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

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

于 2019-03-06T08:05:04.730 回答
1

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

于 2020-06-27T18:13:14.540 回答
1

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

于 2020-05-25T10:28:59.257 回答
0

当我在 ~/.aws/credentials 中为密钥加上引号时,我得到了这个。

aws_secret_access_key = "密钥"

于 2020-03-24T04:45:51.030 回答
0

在我的情况下,api调用参数的错误顺序导致了这种情况。

例如,当我打电话时,/api/call1?parameter1=x&parameter2=y我收到以下消息:

“请求的签名与计算的签名不匹配。”

交换参数后:/api/call1?parameter2=y&parameter1=xapi 调用按预期工作。

非常令人沮丧,因为 api 文档本身的参数顺序不同。这也不是发生这种情况的唯一电话。

于 2021-08-11T05:38:25.837 回答
0

奇怪的是我以前有一个错误The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256。Stackoverflow 上有一个答案,需要添加AWS_S3_REGION_NAME = 'eu-west-2' (your region), AWS_S3_SIGNATURE_VERSION = "s3v4

这样做之后,之前的错误被清除了,但我再次遇到了这个签名错误。搜索答案,直到我最终删除了AWS_S3_SIGNATURE_VERSION = "s3v4Then 它起作用了。把它放在这里也许它可以帮助某人。顺便说一句,我正在使用 Django。

于 2020-08-16T15:01:35.103 回答
0

就我而言,在将文件上传到存储桶并为它们生成预签名 URL 之间,我不得不等待几个小时。

于 2020-04-08T11:57:54.603 回答
0

在我的情况下,我调用s3request.promise().then()了 incorreclty,这导致在只完成一个调用时发生了两次请求执行。

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

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

于 2019-04-25T21:06:12.080 回答
0

由于以下原因,我得到了同样的错误。

我输入了正确的凭据,但使用了复制粘贴。所以这可能是复制粘贴时插入垃圾字符的问题。我已经手动输入并运行了代码,现在它工作正常

谢谢你

于 2019-09-26T06:07:43.833 回答
0

这些变化对我有用。修改了代码

FROM: const s3 = new AWS.S3();

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

将方法调用从 POST 更改为 PUT。

于 2021-09-03T14:56:27.197 回答
0

在我的情况下,问题是用于配置 Amplify 的 API Gateway URL 最后有一个额外的斜线......

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

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

于 2019-03-29T17:08:12.137 回答
0

awscli当使用Debian 伸展可用的最新版本(即版本 1.11.13 )时,我在具有非 AWS S3 端点的 Docker 映像中遇到了这种情况。

升级到 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
于 2019-01-07T12:40:31.900 回答
0

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

于 2021-08-19T10:46:58.737 回答
0

只是为了增加这可以显示的许多不同方式。

如果您在 iOS 上使用 Safari 并连接到 Safari Technology Preview 控制台 - 您将看到同样的问题。如果您从控制台断开连接 - 问题就会消失。

当然,它使其他问题的故障排除变得困难,但它是 100% 的重现。

我试图弄清楚我可以在 STP 中改变什么来阻止它这样做,但还没有找到它。

于 2020-02-13T03:34:06.850 回答
0

我不得不设置

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

在使用 ruby​​ aws sdk v2 之前(在其他语言中可能也有类似的东西)

于 2019-01-16T14:07:55.177 回答
0

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

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

于 2018-11-28T13:33:56.950 回答
0

我在 c# 中遇到了同样的问题。反过来,问题出在当您尝试直接访问它时,restsharp 返回正文的方式。在我们的例子中,它与 /feeds/2021-06-30/documents 端点一起使用:

{
    "contentType":"text/xml; charset=UTF-8"
}

问题是当尝试在 HashRequestBody 方法上的 AWSSignerHelper 类上签署请求时,您有以下代码:

 public virtual string HashRequestBody(IRestRequest request)
    {
        Parameter body = request.Parameters.FirstOrDefault(parameter => ParameterType.RequestBody.Equals(parameter.Type));
        string value = body != null ? body.Value.ToString() : string.Empty;
        return Utils.ToHex(Utils.Hash(value));
    }

此时 body.Value.ToString() 的值将是:

{contentType:text/xml; charset=UTF-8}

它缺少restsharp在发布请求时添加的双引号,但是当您访问这样的值时,它不会给出无效的哈希值,因为该值与发送的值不同。

我暂时用它替换了代码,它可以工作:

public virtual string HashRequestBody(IRestRequest request)
    {
        Parameter body = request.Parameters.FirstOrDefault(parameter => ParameterType.RequestBody.Equals(parameter.Type));
        string value = body != null ? body.Value.ToString() : string.Empty;
        if (body?.ContentType == "application/json")
        {
            value = Newtonsoft.Json.JsonConvert.SerializeObject(body.Value);
        }
        return Utils.ToHex(Utils.Hash(value));
    }
于 2021-09-07T15:04:20.547 回答
0

我面临着同样的问题。导致问题的代码片段:

<iframe title="PDF Viewer" src={`${docPdfLink}&embed=true`} />

对我来说,有两个问题

  1. 在链接末尾使用embed导致签名不匹配,因此,问题出现了。
  2. S3 中的文件具有其他内容类型application/pdf,因此我什至在修复第一个点后无法呈现 pdf。

所以,这是我在代码中所做的:

<iframe title="PDF Viewer" src={docPdfLink} />

在 s3 存储桶中:s3 文件内容类型 此外,我们还需要确保每当我们向 s3 添加或创建 pdf 时,它应该具有应用程序内容application/pdf

于 2021-06-23T15:16:57.970 回答
0

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

于 2018-10-09T13:56:42.743 回答
0

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

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

CopyObjectRequest objectRequest = CopyObjectRequest.builder()
                .copySource(URLEncoder.encode(bucket + "/" + oldFileKey, "UTF-8"))
                .destinationBucket(bucket)
                .destinationKey(newFileKey)
                .build();
于 2020-04-07T02:03:09.267 回答
0

根据上传到 S3 存储桶的文件的 java 文档If you are uploading Amazon Web Services KMS-encrypted objects, you need to specify the correct region of the bucket on your client and configure Amazon Web Services Signature Version 4 for added security. For more information on how to do this, see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingAWSSDK.html# specify-signature-version

所以你可能需要配置签名版本 4。

于 2021-12-01T10:10:23.493 回答
0

通过 Java SDK 将文档上传到 CloudSearch 时出现此错误。问题是因为要上传的文档中有一个特殊字符。错误“我们计算的请求签名与您提供的签名不匹配。请检查您的 AWS 秘密访问密钥和签名方法。” 非常具有误导性。

于 2019-07-25T06:23:59.113 回答
0

This mostly happens when you take a SECRET key and pass it to elastic client.

e.g: Secret Key: ABCW1233**+OxMMMMMMM8x**

While configuring in the client, You should only pass: ABCW1233**(The part before the + sign).

于 2020-05-18T09:39:45.637 回答
0

我通过在AWS.S3()中添加apiVersion解决了这个问题,然后它完美地适用于 S3 签名的 url。

从改变

var s3 = new AWS.S3();

var s3 = new AWS.S3({apiVersion: '2006-03-01'});

有关更详细的示例,可以参考这个 AWS Doc SDK 示例: https ://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javascript/example_code/s3/s3_getsignedurl.js

于 2019-11-26T15:15:15.057 回答
0

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

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

于 2022-02-24T01:02:12.980 回答
0

我没有看到任何好的理由,删除存储桶并重新创建它对我有用。

于 2021-04-22T06:08:50.070 回答
0

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

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

于 2022-01-20T13:25:28.287 回答
0

就像其他人说的那样,我遇到了完全相同的问题,结果证明与密码/访问密码有关。我为我的 s3 用户生成了一个无效的密码,它没有通知我。尝试与用户连接时,出现此错误。它似乎不喜欢密码中的某些或所有符号(至少对于 Minio)

于 2019-09-25T17:22:07.997 回答
0

如果您是一名 Android 开发人员,并且正在使用AWS 示例代码中的签名函数,您很可能想知道为什么它ListS3Object有效,但GetS3Object. 这是因为当您设置setDoOutput(true)并使用 GET HTTP 方法时,AndroidHttpURLConnection会将请求切换为 POST。因此,使您的签名无效。检查我原来的问题帖子。

于 2021-11-30T08:10:32.427 回答
-1

我可以通过设置环境变量来解决这个问题。

export AWS_ACCESS_KEY=
export AWS_SECRET_ACCESS_KEY=

在 IntelliJ + py.test 中,我设置了环境变量[Run] > [Edit Configurations] > [Configuration] > [Environment] > [Environment variables]

于 2018-12-14T02:21:02.727 回答