使用预签名 url 将文件发送到 s3 存储桶会出现 403 错误 (SignatureDoesNotMatch)

Sending file to s3 bucket using presigned url gives 403 error (SignatureDoesNotMatch)

我正在我的应用程序的服务器端生成一个预签名的 URL,如下所示:

const s3 = new AWS.S3({
    region: 'us-west-2',
    signatureVersion: 'v4',
});
const params = {
    Bucket: 'bucketName',
    Key: fileName,
    ContentType: 'text/csv',
    Expires: 120
};
    
return s3.getSignedUrl('putObject', params);

然后我尝试使用如下所示的 ajax 调用将文件放入我的 S3 存储桶中:

$.ajax({
    url: url
    type: 'PUT',
    data: file,
    processData: false,
    contentType: 'text/csv',
    success: function () {
        console.log('Uploaded data successfully.');
    },
    error: function (xhr) {
        console.log(xhr);
    }
});

但是,当我尝试这样做时,出现 403 Forbidden 错误并且 XML 显示 SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method.

我已确保 ContentType 与生成预签名 URL 和将文件放入 S3 存储桶时相同。无论我做什么,都无济于事,我仍然收到此 403 错误。我已尝试为 ContentType 执行 binary/octet-stream,但没有成功。我尝试执行 ACL: 'public-read' 但没有成功。 CORS 也在我的存储桶中配置,所以我知道这不是问题所在(我对此有不同的错误)。我确实注意到在网络调用中,它是这样说的:

Request URL: https://bucket-name.s3.us-west-2.amazonaws.com/fileName?Content-Type=text%2Fcsv&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAXBWQUNDKKHHYM5GH%2F20210219%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210219T015308Z&X-Amz-Expires=120&X-Amz-Security-Token=FwoGZXIvYXdzEIv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDOQ1EV3FIT00%2Fuo1BCKyAROysQ9G5PY9RFLeS8GwBLPEo7LCEJWstwki7nZatfddDczn0GKO7GwNEe5Qs%2BsLtMZv2xPTXo3Bwur%2BIhH7jV35HHQm976s1mOf8JZe2g%2BimUGNwLxBKY%2BrhWsN8yryNrd6k1VBRf1R9No9Jh%2FIumuwiVEoFLvVBHtILB9i53FdDo%2BJ8T%2BMCliV22SGBAwPQnYk8xvbo1%2B%2B%2B%2BAu%2FwVFl3tvG2yo7PHLzPpKqcpyJq4pMwko3aK8gQYyLUl0hZCTtit2cvBD5YAo57aMZBdTlpN5Wx3q27PSQZ1d8Bq1lQY%2BIQVkPlxZ%2Fw%3D%3D&X-Amz-Signature=446c16abde4d278c42c72373c85a6d44f959330468076e6bd888a8e2816b2b86&X-Amz-SignedHeaders=host
Request Method: PUT
Status Code: 403 Forbidden
Remote Address: 52.218.246.105:443
Referrer Policy: strict-origin-when-cross-origin

响应Headers:

Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Methods: GET, PUT, POST, DELETE
Access-Control-Allow-Origin: *
Connection: close
Content-Type: application/xml
Date: Fri, 19 Feb 2021 01:53:09 GMT
Server: AmazonS3
Transfer-Encoding: chunked
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method

并且请求 Headers 有 Content-Type: text/csv... 虽然不确定这是否重要

任何帮助将不胜感激。我从字面上搜索了整个 Google,没有人说出于某种原因对我有用..

添加答案,因为我无法发表评论

你能检查一下为什么内容类型没有和“主机”一起出现在你的“X-Amz-Signed-Headers”中吗?

因为这是“params”的一部分,因此也是签名计算的一部分,您应该看到

X-Amz-SignedHeaders=content-type%3Bhost 

而不是?Content-Type=text%2Fcsv

检查您的 API key and secret,因为 SignatureDoesNotMatch 错误通常是指 API 密钥和密码不匹配,请参考之前的答案:

原来是我的桶出了问题,这就是我收到此错误的原因。我尝试写入的存储桶到底有什么不同仍然未知。我尝试了另一个 S3 存储桶,它工作正常