繁体   English   中英

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

[英]generate_presigned_url boto3 generates same URL until expiry when called using cloudfront

我正在尝试生成预签名 URL 的 s3。逻辑是用 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。 但是,如果我添加云端并调用云端域名,那么将生成相同的 URL,直到 URL 过期。 为什么我不像案例 1 那样每次调用都得到不同的 URL?

您需要为 CloudFront 创建签名者,并使用来自签名者的generate_presigned_url 每次尝试时,此代码段都会生成不同的 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或类似内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM