generate_presigned_url boto3 在使用 cloudfront 调用时生成相同的 URL 直到过期

Posted

技术标签:

【中文标题】generate_presigned_url boto3 在使用 cloudfront 调用时生成相同的 URL 直到过期【英文标题】:generate_presigned_url boto3 generates same URL until expiry when called using cloudfront 【发布时间】:2021-10-20 23:00:58 【问题描述】:

我正在尝试生成 s3 预签名 URL。逻辑是用 Lambda@Edge, python 3.7 编写的

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    s3 = boto3.client('s3',config=Config(signature_version='s3v4'))
    url = s3.generate_presigned_url(ClientMethod='get_object',
                                    Params='Bucket': 'BUCKET_NAME',
                                            'Key':'abc.jpeg'
                                           ,
                                    ExpiresIn=3600)
    response = 
     'status': '302',
     'statusDescription': 'Found',
     'headers': 
         'location': [
             'key': 'Location',
             'value': url
         ]
     
     
    return response

当我仅在 Lambda 中测试此代码时,每次调用都会得到不同的 URL。但是,如果我添加 cloudfront 并调用 cloudfront 域名,则会生成相同的 URL,直到 URL 过期。 为什么我没有像案例 1 那样为每个调用获得不同的 URL?

【问题讨论】:

您能否展示一下您的 CloudFront 预签名 URL 生成例程?我可以使用 Boto3 获得不同的 URL。 【参考方案1】:

您需要为 CloudFront 创建一个签名者,并使用签名者的generate_presigned_url。这个 sn-p 每次尝试都会生成不同的 URL。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from datetime import datetime, timedelta

from botocore.signers import CloudFrontSigner
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

from cf_url_gen.config import Bucket, Operation, config


class CFClient(object):
    """CloudFront client class

    Creates a CloudFront client object for generting S3 resource URLs.
    """

    def __init__(
        self,
        cf_key_id: str = os.getenv("CF_KEY_ID"),
        cf_key_path: str = os.getenv("CF_KEY_PATH"),
        cf_ttl_sec: int = 300,
    ):
        """The __init__ method for CFClient class

        Args:
            cf_key_id (str, optional): CloudFront key id, can be set via environment variable `CF_KEY_ID`
            cf_key_path (str, optional): CloudFront key path, can be set via environment variable `CF_KEY_PATH`
            cf_ttl_sec (int, optional): URL validity duration from UTC timestamp, default value 300 seconds
        """
        with open(cf_key_path, "rb") as key_file:
            _key = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend())
            self.signer = CloudFrontSigner(cf_key_id, lambda m: _key.sign(m, padding.PKCS1v15(), hashes.SHA1()))
        self.ttl = cf_ttl_sec

    def get_url_with_prefix(self, file_path: str, url_prefix: str, is_signed: bool = True) -> str:
        """Method for generating CloudFront URLs for file paths with given url prefix

        Args:
            file_path (str): Full file path in S3 bucket excluding bucket name
            url_prefix (str): URL prefix to use for signing or generating S3 resource URL
            is_signed (bool): Flag indicating whether URL should be signed or not

        Returns:
            CloudFront url string based on provided signing options
        """
        if not is_signed:
            return os.path.join(url_prefix, file_path)
        else:
            end_date = datetime.utcnow() + timedelta(seconds=self.ttl)
            file_url = os.path.join(url_prefix, file_path)
            return self.signer.generate_presigned_url(file_url, date_less_than=end_date)

注意: URL 前缀应该是您的 S3 存储桶的 CloudFront 域 URL,通常类似于 https://bucketname.yourdomain.com 或类似的东西。

【讨论】:

以上是关于generate_presigned_url boto3 在使用 cloudfront 调用时生成相同的 URL 直到过期的主要内容,如果未能解决你的问题,请参考以下文章

SAP中BW和BO有啥区别

Mybatis自动生成的BO对象继承公共父类(BO中过滤掉公共属性)

医学上bo是啥意思(bo在医学上是啥意思)

BO 与 VO 的属性拷贝 copyProperties(bo,vo)

java中的bo怎么理解?怎么运用

我的BO之数据保护