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 functions
和API Gateway
时,
这里需要考虑的事情很少,
-
在使用预签名 URL 时,请检查您的请求方法是
PUT
还是 POST
。它应该是PUT。
在 AWS 中检查您的 lambda function
,并确保 ContentType
与您的上传匹配。
确保您在请求中设置的 headers
与 lambda 中的 params
匹配。功能。
【讨论】:
【参考方案3】:不确定由我们的后端团队维护的 s3 存储桶策略方面。但是我能够使用post
和put
方法将文件上传到我们的公共资产存储桶。
发布
生成预签名 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 秘密访问密钥和签名方法
AWSSecretsManagerException:我们计算的请求签名与您提供的签名不匹配
为啥会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch?