python - 带有 boto3 的 AWS S3 预签名 url - 签名不匹配

标签 python amazon-web-services amazon-s3 boto3

我想为我的存储桶中的对象创建一个预签名的 url。我使用以下 python 代码:

    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() 方法。这在其他项目中运行良好,但在这里我只收到错误:

The request signature we calculated does not match the signature you provided. Check your key and signing method.

这很奇怪。用户应该拥有所有必要的权利。因为列出我存储桶中的所有文件工作正常。

有人可以为我指明正确的方向,为什么这不起作用?

编辑

如果这有帮助,我会在前端使用 next.js。

最佳答案

遇到了完全相同的问题。研究了 AWS 文档并自己编写了(签名 v4)程序。以下是基于

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

关于python - 带有 boto3 的 AWS S3 预签名 url - 签名不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50213740/

相关文章:

amazon-web-services - 有没有办法从 aws Web 控制台获取 s3 uri?

python - 按与字符串相关的列错误合并 2 个 csv 文件?

python - 从大文件中删除确切的字符串?

amazon-web-services - 通过 ALB 和 Lambda 集成提供二进制响应

amazon-web-services - S3 "US Standard"区域与 EC2 中的 "us-east-1"区域相同吗?

amazon-web-services - 我正在尝试使用 aws-cli 启动一个 ec2 实例(即 ubuntu ami),并且我想从我之前创建的 s3 存储桶中复制我的代码

ios - 以编程方式将默认加密 KMS 添加到存储桶

amazon-web-services - 如何通过特定用户的 Bearer token 访问与 S3 Bucket 连接的 AWS CloudFront(JWT 自定义身份验证)

python - pycrypto 需要 Visual Studio 吗?

python - 在numpy中按行获取范围