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

Javascript AWS S3-我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法,javascript,node.js,amazon-web-services,amazon-s3,aws-sdk-nodejs,Javascript,Node.js,Amazon Web Services,Amazon S3,Aws Sdk Nodejs,我正在尝试使用从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, reg

我正在尝试使用从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>/*"
        }
    ]
}

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

使用
API网关的
Lambda函数时,
这里没有什么值得考虑的事情,

  • 使用预签名URL时,检查您的请求方法是
    PUT
    还是
    POST
    。它应该是PUT
  • 检查AWS中的
    lambda函数
    ,确保
    ContentType
    与您的上传匹配
  • 确保为请求设置的
    标题
    与lambda中的
    参数匹配。功能

  • 不确定s3 bucket策略端,它由我们的后端团队维护。但我能够使用
    post
    put
    方法将文件上传到我们的公共资产桶中

    邮递 生成预签名的URL

    response = s3.generate_presigned_post(Bucket=BUCKET,
                                            Key=KEY,
                                            ExpiresIn=3600)
    
    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 = s3.generate_presigned_url('put_object',
                                 ExpiresIn=3600,
                                 Params={"Bucket": BUCKET,
                                 "Key": KEY,
                                 "ContentType": "application/octet-stream"})
    
    headers = {'content-type': 'application/octet-stream'}
    with open(file_path_, 'rb') as f:
        http_response = requests.put(url=url, data=f, headers=headers)
    
    
    使用预先签名的URL上传文件

    response = s3.generate_presigned_post(Bucket=BUCKET,
                                            Key=KEY,
                                            ExpiresIn=3600)
    
    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 = s3.generate_presigned_url('put_object',
                                 ExpiresIn=3600,
                                 Params={"Bucket": BUCKET,
                                 "Key": KEY,
                                 "ContentType": "application/octet-stream"})
    
    headers = {'content-type': 'application/octet-stream'}
    with open(file_path_, 'rb') as f:
        http_response = requests.put(url=url, data=f, headers=headers)
    
    
    生成预签名的URL

    response = s3.generate_presigned_post(Bucket=BUCKET,
                                            Key=KEY,
                                            ExpiresIn=3600)
    
    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 = s3.generate_presigned_url('put_object',
                                 ExpiresIn=3600,
                                 Params={"Bucket": BUCKET,
                                 "Key": KEY,
                                 "ContentType": "application/octet-stream"})
    
    headers = {'content-type': 'application/octet-stream'}
    with open(file_path_, 'rb') as f:
        http_response = requests.put(url=url, data=f, headers=headers)
    
    
    使用预先签名的URL上传文件

    response = s3.generate_presigned_post(Bucket=BUCKET,
                                            Key=KEY,
                                            ExpiresIn=3600)
    
    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 = s3.generate_presigned_url('put_object',
                                 ExpiresIn=3600,
                                 Params={"Bucket": BUCKET,
                                 "Key": KEY,
                                 "ContentType": "application/octet-stream"})
    
    headers = {'content-type': 'application/octet-stream'}
    with open(file_path_, 'rb') as f:
        http_response = requests.put(url=url, data=f, headers=headers)
    
    

    确保添加
    headers={'content-type':'application/octet stream'}
    如果您使用
    put
    方法

    您说您正在尝试“上载”图像,但根据错误消息,您正在使用此签名URL发出
    获取
    (而不是
    put
    )请求。由于请求与签名不匹配,该操作预计将失败。您的解决方案对我有效。您的
    桶策略对我有效,谢谢。是的。使用
    PUT
    为我解决了这个问题。