簡體   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