【问题标题】:AWS S3 - The request signature we calculated does not match the signature you provided. Check your key and signing methodAWS S3 - 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法
【发布时间】: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 为我解决了这个问题。

标签: javascript node.js amazon-web-services amazon-s3 aws-sdk-nodejs


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    1. 在使用预签名 URL 时,请检查您的请求方法是 PUT 还是 POST。它应该是PUT
    2. 在 AWS 中检查您的 lambda function,并确保 ContentType 与您的上传匹配。
    3. 确保您在请求中设置的 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'}

      【讨论】:

        猜你喜欢
        • 2019-12-01
        • 2015-12-31
        • 2021-04-11
        • 1970-01-01
        • 2022-01-05
        • 2015-05-18
        • 2015-06-01
        • 2017-07-23
        相关资源
        最近更新 更多