首页 > 编程问答 >使用带有私钥的云前端生成签名 URL 的问题..使用 Python 3.7 为带有空格的 S3 对象生成签名 URL

使用带有私钥的云前端生成签名 URL 的问题..使用 Python 3.7 为带有空格的 S3 对象生成签名 URL

时间:2024-07-25 07:55:55浏览次数:13  
标签:python amazon-cloudfront pre-signed-url botocore

我在使用 Python 3.7 为 S3 对象生成签名 URL 时遇到问题。具体来说,键中带有空格的对象的 URL 会导致“访问被拒绝”错误,而没有空格的对象的 URL 通常工作正常。但是,并非所有不带空格的对象都能正常工作,带空格的对象始终会失败。

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


class SecuringCloudFront:
    def __init__(self):
        pass

    def rsa_signer(self, message):
        try:
            with open('private_key.pem', 'rb') as key_file:
                private_key = serialization.load_pem_private_key(
                    key_file.read(),
                    password=None,
                    backend=default_backend()
                )
            return private_key.sign(message, padding.PKCS1v15(), hashes.SHA1())
        except Exception as e:
            print(f"Error loading or signing with private key: {e}")
            return None

    def get_document_images_from_s3(self, images_keys, images_to_get=None):
        """
        Description: creates signed CloudFront URLs for document images

        

        Attributes:
        - images_keys: list of keys
        - images_to_get: list of images index

        Result: list of URLs
        """
        CLOUDFRONT_URL = "https://***********.cloudfront.net"
        KEY_PAIR_ID = "********" #id of stored key 

        images_urls = []
        keys = (
            images_to_get
            if images_to_get is not None
            else list(range(len(images_keys)))
        )
        for key in keys:
            try:
                if key >= len(images_keys) or len(images_keys[key]["name"]) == 0:
                    continue

                s3_key = images_keys[key]["name"]
                url = f"{CLOUDFRONT_URL}/{s3_key}"
                expire_date = datetime.utcnow() + timedelta(hours=24)

                cloudfront_signer = CloudFrontSigner(KEY_PAIR_ID, self.rsa_signer)
                signed_url = cloudfront_signer.generate_presigned_url(
                    url, date_less_than=expire_date
                )
                url = {"url": signed_url} if signed_url else {"url": ""}
            except Exception as e:
                url = {"url": ""}
                print(f"Error generating signed URL: {e}")

            images_urls.append(url)

        return images_urls


if __name__ == "__main__":
    securing_cloud_front = SecuringCloudFront()
    images_keys = [
        {"name": "imageIns3.jpg"}
    ]
    signed_urls = securing_cloud_front.get_document_images_from_s3(images_keys)
    print("Signed URLs:", signed_urls)

用 %20 和 + 替换空格:

我尝试用 URL 中的 %20 和 + 替换对象键中的空格。此方法没有解决问题,我仍然收到“访问被拒绝”错误。 集成自定义策略:

我尝试集成用于签名 URL 生成的自定义策略,但无法理解如何正确应用它。尽管进行了各种尝试,我仍无法使用此方法解决问题。

其他信息:当尝试直接从 s3 打开无法从 CloudFront 获取有效 URL 的对象时,该对象被归类为“jpg_files”。从 CloudFront 成功检索到的对象被分类为“jpg_images”


当然,我可以帮助解决这个问题。在为带有空格的 S3 对象生成签名的 CloudFront URL 时遇到的问题很常见。以下是解决方案和需要检查的事项的细分:

理解问题

观察到的行为(有些对象有效而有些无效)表明问题不在于空格本身,而在于 S3 存储桶中对象的权限或元数据不一致。 让我们逐步解决这个问题。

逐步调试和解决方案

  1. S3 存储桶策略验证: 确保的 S3 存储桶策略明确允许来自的 CloudFront 发行版的访问。以下是一个示例策略:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontAccess",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}
  • 替换:

    • your-bucket-name :的 S3 存储桶的实际名称。
    • 如果使用的是自定义来源身份,请使用以下方法更新 Principal json "Principal": { "AWS": "arn:aws:iam::your-account-id:user/your-cloudfront-origin-identity-username" }
  • CloudFront 发行版配置:

  • 来源域名称: 在的 CloudFront 发行版配置中,请仔细检查来源域名称是否指向的 S3 存储桶(例如, your-bucket-name.s3.amazonaws.com )。

  • 来源访问身份: 为的 CloudFront 发行版创建一个或使用现有的来源访问身份 (OAI)。这允许 CloudFront 代表访问的 S3 存储桶。 不要使用的 AWS 根用户或个人用户凭据。

  • 对象权限:

  • 一致性: 确保所有对象(带有和不带有空格的对象)都具有与其关联的 一致 权限。理想情况下,它们应该继承自存储桶策略,或者应该对每个对象设置明确的权限。

  • 直接授予: 如果需要更精细的控制,请使用访问控制列表 (ACL) 或存储桶策略直接向 CloudFront OAI 授予对这些对象的权限。

  • URL 编码:

  • 是对的,空格在 URL 中应正确编码为 %20 + 通常用于替换 URL 查询字符串中的空格,而不是路径本身。

  • Boto3 处理: 好消息是,Boto3 库(正在使用的库)通常会自动为处理 URL 编码。因此,在大多数情况下,无需手动执行此操作。

  • 代码审查:

  • 的代码片段看起来正确,因为它使用了 CloudFrontSigner ,它应该可以处理 URL 签名过程。

故障排除技巧

  • 逐步测试: 首先尝试一个没有空格的简单对象名称。一旦有效,请逐步引入更复杂的对象名称(例如,带有空格的对象名称)。
  • CloudFront 日志: 启用 CloudFront 日志以获取有关失败请求的详细见解,包括返回的状态代码以及可能有助于查明问题的任何错误消息。
  • S3 访问日志: 同样,启用 S3 访问日志以查看 CloudFront 是否正在访问预期对象,以及是否有任何授权错误。

如果在执行这些步骤后仍然遇到问题,请提供以下信息,以便我进一步帮助:

  • 来自 CloudFront 日志的相关错误消息(如果有)。
  • 使用的特定 CloudFront 发行版配置(省略敏感信息)。
  • 受影响 S3 对象的示例对象键(带有空格)。

标签:python,amazon-cloudfront,pre-signed-url,botocore
From: 78787741

相关文章

  • 有没有更好的方法来在存储库中的一组 python 程序之间共享公共代码
    当我想要快速、轻松地做许多不同的事情时,我会选择Python-即我总是会得到许多Python“程序”-例如一组脚本-或者如果我正在玩一些东西,一堆测试程序等-即始终是许多不同程序的松散集合。但是,我会分享某些内容。例如,如果我正在使用AI-我可能有30个左右完全不相......
  • 如何在Python中从两个不同长度的列表创建DataFrame,为第二个列表中的每个值重复第一个
    我是一个超级初学者,所以请耐心等待。我觉得这应该很容易,但我无法弄清楚。我不确定是否应该创建两个列表,然后将它们组合起来,或者是否有办法以这种方式直接创建DataFrame。我需要一列包含这些值:df=pd.DataFrame({'x1':np.linspace(-2.47,2.69,num=101)})然后我将值A......
  • Python multiprocessing.connection.Connection 的行为不符合规范
    根据python规范,recv()pythonConnection的方法,(从multiprocessing.Pipe()返回,当管道为空且管道的另一端关闭时抛出EOFError(这里参考:https://docs.python.org/3.9/library/multiprocessing.html#multiprocessing.connection.Connection.re......
  • 使用 python Flask 发送邮件中的图像
    我想发送一封包含html代码和图像的电子邮件但在gmail中它说图像已附加,我不想要这样,我只想要电子邮件正文中的图像。html_content=f"<imgsrc="cid:banner"alt=""style="width:80%;">"msg=MIMEMultipart('related')html_part=MIMEText(html_c......
  • 在 python requests modul 中,如何检查页面是否使用“POST”方法或“GET”方法
    如何使用python“requests”模块检查页面是否使用“GET”方法或“POST”方法。我期望输出为True或False,或者GET或Post预期代码:importrequestsurl=f"www.get_example.com"response=requests.get(url)ifresponse.check_get==True:print("get")你......
  • VS Code Python - 如果括号(括号、大括号等)未关闭,内联建议不起作用
    我遇到的问题是,当我在未闭合的括号或方括号“内部”开始变量名称时,VSCode将不会显示任何建议。但是,如果在键入变量名称之前闭合括号,则建议效果很好。如果我可以避免它,我宁愿不将自动完成括号关闭设置为True也不使用TabOut扩展。第一个屏幕截图显示建议在闭括号/方......
  • 在 Azure 上部署代码时使用 Python 的多处理模块是否有意义?
    我们的团队在Azure机器学习(AML)上部署了一个Python脚本来处理存储在Azure存储帐户上的文件。我们的管道由一个ForEach活动组成,该活动调用每个或列出的文件的Python脚本。从Azure数据工厂(ADF)运行它会触发多个单独的管道同时运行......
  • 我已成功安装 pypdf2 但无法将其导入到我的 python 文件中
    我已经成功安装了pypdf2模块,但在导入它时,我发现该模块丢失了。我尝试使用fromPyPDF2importPdfReader导入,但它不起作用此问题的各种解决方案是什么?在尝试导入PyPDF2时遇到问题。以下是可能导致此问题的一些常见原因和解决方案:安......
  • Python3打开图片时请求ConnectionResetError(10054)
    我试图从'http://xxx.jpg'之类的网站下载图片。代码:headers={'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/66.0.3359.139Safari/537.36'}url='http://xxx.jpg'resp......
  • Jupyter Notebook 环境中的 Python 版本不匹配
    我遇到Jupyter笔记本启动横幅中报告的Python版本与我在笔记本中查询python--version时显示的版本之间的差异。启动横幅指示Python3.11.9,但是当我运行!python--version时,它返回Python3.11.7。我所做的步骤:basecondahas3.11.7versio......