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

Posted

技术标签:

【中文标题】AWS S3 - 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法【英文标题】:AWS S3 - The request signature we calculated does not match the signature you provided. Check your key and signing method 【发布时间】:2020-11-06 20:31:55 【问题描述】:

我正在尝试使用从 aws sdk 生成的预签名 url 将图像上传到 s3。

router.get('/upload-url', async(req, res) => 
    try 

        AWS.config.update(
            secretAccessKey: process.env.AWS_SECRET_ACCESS,
            accessKeyId: process.env.AWS_ACCESS_KEY,
            region: 'ap-southeast-1'

        );

        const s3 = new AWS.S3();
        var params =  Bucket: process.env.bucket_name, Key: 'products', ContentType: 'image/jpeg' ;
        s3.getSignedUrl('putObject', params, function(err, url) 
            if (err) 
                throw (err)
            
            res.status(200).send( link: url )
        )

     catch (err) 
        res.status(400).send( message: err.message )
    
)

上面的返回url,当我尝试访问它时会出错

<Error>
<script class="__REQUESTLY__SCRIPT">(function(namespace)  window[namespace] = window[namespace] || ; window[namespace].responseRules = ; let open = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method)  this.addEventListener('readystatechange', function()  if (this.readyState === 4 && window[namespace].responseRules.hasOwnProperty(this.responseURL))  const responseRule = window[namespace].responseRules[this.responseURL]; const response, id = responseRule; const responseType = this.responseType; let customResponse; customResponse = response.type === 'code' ? responseRule.evaluator( method, url: this.responseURL, requestHeaders: this.requestHeaders, requestData: this.requestData, responseType: this.responseType, response: this.response ) : response.value; Object.defineProperty(this, 'response',  get: function ()  if (response.type === 'static' && responseType === 'json')  return JSON.parse(customResponse);  return customResponse;  ); if (responseType === '' || responseType === 'text')  Object.defineProperty(this, 'responseText',  get: function ()  return customResponse;  );  window.postMessage( from: 'requestly', type: 'response_rule_applied', id , window.location.href);  , false); open.apply(this, arguments); ; let send = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data)  this.requestData = data; send.apply(this, arguments); ; let setRequestHeader = XMLHttpRequest.prototype.setRequestHeader; XMLHttpRequest.prototype.setRequestHeader = function(header, value)  this.requestHeaders = this.requestHeaders || ; this.requestHeaders[header] = value; setRequestHeader.apply(this, arguments);  )('__REQUESTLY__')</script>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<AWSAccessKeyId>DHAWUIHDUIAWHDAWUI</AWSAccessKeyId>
<StringToSign>GET 1594960145 /bucketname/products</StringToSign>
<SignatureProvided>oD2y%2Ftv04ernxLiNdMAETiebi1KXY%3D</SignatureProvided>
<StringToSignBytes>47 45 54 0a 0a 0a 31 35 30 34 39 36 30 31 34 35 0a 2f 64 65 76 2e 6b 6f 6c 2e 73 68 6f 70 2f 70 70 6f 64 75 63 74 73</StringToSignBytes>
<RequestId>11A7BD415D04AAFE7E</RequestId>
<HostId>3zFeVQCbO+LraKZ7sR1j7rgMR9KdyOEqKFGX/5QCWXMhXLBubzre7Lb1eun/zATJU/xz69mpg+o=</HostId>
</Error>

我一直在寻找其他帖子,但尚未找到解决方案。

我发现的一些建议是:

不要在秘密访问密钥中包含“/”。 (我的密钥不包含斜线) 凭据不正确(我已经使用 aws cli 测试了密钥,它可以正常工作) 更新存储桶权限和策略。 (我已经更新了政策的所有访问权限)

我的bucket设置如下:

存储桶策略


    "Version": "2012-10-17",
    "Id": "Policy1594951813323",
    "Statement": [
        
            "Sid": "Stmt15949510950",
            "Effect": "Allow",
            "Principal": 
                "AWS": "arn:aws:iam::<AccountNumber>:root"
            ,
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::<bucketname>/*"
        
    ]

CORS 配置

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>


更新的解决方案

Use PUT Instead of POST for the pre-sign url to upload file to S3

【问题讨论】:

您说您正在尝试“上传”图像,但根据错误消息,您正在使用此签名 URL 发出 GET(而不是 PUT)请求。预计会失败,因为请求与签名不匹配。 您的Bucket Policy 为我工作,谢谢。 是的。使用PUT 为我解决了这个问题。 【参考方案1】:

我通过重新创建密钥对解决了这个问题。事实证明,我的密钥以等号“=”开头。这不仅与下载的 CSV 混淆,而且我的猜测是与签名生成解析软件混淆。重新生成密钥对使系统正常工作。

【讨论】:

【参考方案2】:

在使用Lambda functionsAPI Gateway 时, 这里需要考虑的事情很少,

    在使用预签名 URL 时,请检查您的请求方法是 PUT 还是 POST。它应该是PUT。 在 AWS 中检查您的 lambda function,并确保 ContentType 与您的上传匹配。 确保您在请求中设置的 headers 与 lambda 中的 params 匹配。功能。

【讨论】:

【参考方案3】:

不确定由我们的后端团队维护的 s3 存储桶策略方面。但是我能够使用postput 方法将文件上传到我们的公共资产存储桶。

发布

生成预签名 URL

response = s3.generate_presigned_post(Bucket=BUCKET,
                                        Key=KEY,
                                        ExpiresIn=3600)

使用预签名 URL 上传文件

signed_url_post = response['url']
data = response['fields']
key = response['key']

file_path = [YOUR_FILE_PATH]
with open(file_path, 'rb') as f:
    files = 'file': (file_path, f)
    http_response = requests.post(url=signed_url_post, data=data, files=files)

生成预签名 URL

url = s3.generate_presigned_url('put_object',
                             ExpiresIn=3600,
                             Params="Bucket": BUCKET,
                             "Key": KEY,
                             "ContentType": "application/octet-stream")

使用预签名 URL 上传文件

headers = 'content-type': 'application/octet-stream'
with open(file_path_, 'rb') as f:
    http_response = requests.put(url=url, data=f, headers=headers)

如果你使用put方法,请确保添加headers = 'content-type': 'application/octet-stream'

【讨论】:

以上是关于AWS S3 - 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法的主要内容,如果未能解决你的问题,请参考以下文章

我们计算的请求签名与您提供的 aws 签名不匹配

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

AWSSecretsManagerException:我们计算的请求签名与您提供的签名不匹配

为啥会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch?

SignatureDoesNotMatch 错误使用 restTemplate 获取 S3 的 url 请求

使用 Amazon API MWS 进行签名查询