带有 boto3 的 AWS S3 预签名网址 - 签名不匹配 [英] AWS S3 presigned urls with boto3 - Signature mismatch

查看:58
本文介绍了带有 boto3 的 AWS S3 预签名网址 - 签名不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为我的存储桶中的对象创建一个预先签名的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆