带有 boto3 的 AWS S3 预签名网址 - 签名不匹配 [英] AWS S3 presigned urls with boto3 - Signature mismatch
问题描述
我想为我的存储桶中的对象创建一个预先签名的 url.我使用以下python代码:
I want to create a presigned url for the objects in my bucket. I use the following python code:
client = boto3.client(
's3',
aws_access_key_id=os.environ['AWS_ACCESS_KEY'],
aws_secret_access_key=os.environ['AWS_SECRETS_KEY'],
config=botocore.client.Config(signature_version='s3v4'),
region_name='eu-central-1'
)
url = client.generate_presigned_url(
ClientMethod='get_object',
ExpiresIn=60,
Params={
'Bucket': MYBUCKET,
'Key': MYKEY
})
然后我将生成的 URL 发送到我的前端.在客户端上,我将使用生成的链接创建一个标签,并在其上使用 click() 方法.这在其他项目中运行良好,但在这里我只收到错误:
I then send the generated URL to my frontend. On the client I will create an a tag with the generated link and use the click() method on it. This worked fine in other projects but here I only get the error:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
这很奇怪.用户应该拥有所有必要的权限.因为列出我的存储桶中的所有文件工作正常.
Which is strange. The user should have all the necessary rights. Because listing all the files in my bucket works fine.
有人能指出我为什么这不起作用的正确方向吗?
Can someone point me in the right direction why this isn't working?
编辑
如果有帮助,我将在前端使用 next.js.
I'm using next.js on the frontend if this is of help.
推荐答案
遇到了完全相同的问题.研究了 AWS 文档并自己编写了(签名 v4)程序.以下内容基于
Had the exact same problem. Studied the AWS docs and wrote the (signature v4) procedure myself. The below is based on
https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
并且完美运行.
ENCODING = 'utf8'
SEVEN_DAYS = 604800
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def sign(key, msg):
return hmac.new(key, msg.encode(ENCODING), hashlib.sha256).digest()
def get_signature_key(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode(ENCODING), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
def generate_presigned_s3_get(bucket, object_key, region, expires_in, access_key, secret_key):
METHOD = 'GET'
SERVICE = 's3'
host = bucket + '.s3.' + region + '.amazonaws.com'
endpoint = 'https://' + host
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
canonical_uri = '/' + object_key
canonical_headers = 'host:' + host + '\n'
signed_headers = 'host'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + SERVICE + '/' + 'aws4_request'
canonical_querystring = '?X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
canonical_querystring += '&X-Amz-Date=' + amz_date
canonical_querystring += '&X-Amz-Expires=' + str(expires_in)
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
canonical_request = METHOD + '\n' + canonical_uri + '\n' + canonical_querystring[1:] + '\n' + canonical_headers + '\n' + signed_headers + '\nUNSIGNED-PAYLOAD'
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode(ENCODING)).hexdigest()
signing_key = get_signature_key(secret_key, datestamp, region, SERVICE)
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
canonical_querystring += '&X-Amz-Signature=' + signature
url = endpoint + canonical_uri + canonical_querystring
logger.info('presigned url: %s' % url)
return url
我也向 boto3 peeps 报告了这个问题:https://github.com/boto/boto3/issues/1644
I've also reported this issue to boto3 peeps: https://github.com/boto/boto3/issues/1644
这篇关于带有 boto3 的 AWS S3 预签名网址 - 签名不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!