为 Amazon CloudFront 创建签名 URL [英] Creating Signed URLs for Amazon CloudFront

查看:29
本文介绍了为 Amazon CloudFront 创建签名 URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简短版本:如何使用 Python 使用 Amazon CloudFront/S3按需"制作签名 URL 以模仿 Nginx 的 X-Accel-重定向行为(即保护下载).

Short version: How do I make signed URLs "on-demand" to mimic Nginx's X-Accel-Redirect behavior (i.e. protecting downloads) with Amazon CloudFront/S3 using Python.

我已经启动了一个 Django 服务器并运行了一个 Nginx 前端.我一直受到对它的请求的打击,最近不得不将它安装为 Tornado WSGI 应用程序以防止它在 FastCGI 模式下崩溃.

I've got a Django server up and running with an Nginx front-end. I've been getting hammered with requests to it and recently had to install it as a Tornado WSGI application to prevent it from crashing in FastCGI mode.

现在我的服务器出现问题,由于对它的媒体请求太多,我的服务器陷入困境(即它的大部分带宽都被用光了),我一直在研究 CDN,我相信亚马逊CloudFront/S3 对我来说是合适的解决方案.

Now I'm having an issue with my server getting bogged down (i.e. most of its bandwidth is being used up) due to too many requests for media being made to it, I've been looking into CDNs and I believe Amazon CloudFront/S3 would be the proper solution for me.

我一直在使用 Nginx 的 X-Accel-Redirect 标头来保护文件免遭未经授权的下载,但我在 CloudFront/S3 中没有这种能力——但是它们确实提供了签名 URL.到目前为止,我不是 Python 专家,绝对不知道如何正确创建签名 URL,所以我希望有人能提供一个链接,了解如何按需"制作这些 URL,或者愿意解释如何在这里,将不胜感激.

I've been using Nginx's X-Accel-Redirect header to protect the files from unauthorized downloading, but I don't have that ability with CloudFront/S3--however they do offer signed URLs. I'm no Python expert by far and definitely don't know how to create a Signed URL properly, so I was hoping someone would have a link for how to make these URLs "on-demand" or would be willing to explain how to here, it would be greatly appreciated.

此外,这是正确的解决方案吗?我对 CDN 不太熟悉,有没有更适合这个的 CDN?

Also, is this the proper solution, even? I'm not too familiar with CDNs, is there a CDN that would be better suited for this?

推荐答案

Amazon CloudFront 签名 URL 与 Amazon S3 签名 URL 的工作方式不同.CloudFront 使用基于单独 CloudFront 密钥对的 RSA 签名,您必须在您的 Amazon Account Credentials 页面中设置该密钥对.以下是使用 M2Crypto 库在 Python 中实际生成限时 URL 的一些代码:

Amazon CloudFront Signed URLs work differently than Amazon S3 signed URLs. CloudFront uses RSA signatures based on a separate CloudFront keypair which you have to set up in your Amazon Account Credentials page. Here's some code to actually generate a time-limited URL in Python using the M2Crypto library:

为 CloudFront 创建密钥对

我认为唯一的方法是通过亚马逊的网站.进入您的 AWS帐户"页面,然后单击安全凭证"链接.单击密钥对"选项卡,然后单击创建新的密钥对".这将为您生成一个新的密钥对并自动下载一个私钥文件(pk-xxxxxxxxx.pem).保持密钥文件的安全和私密.还要记下来自亚马逊的密钥对 ID",因为我们将在下一步中用到它.

I think the only way to do this is through Amazon's web site. Go into your AWS "Account" page and click on the "Security Credentials" link. Click on the "Key Pairs" tab then click "Create a New Key Pair". This will generate a new key pair for you and automatically download a private key file (pk-xxxxxxxxx.pem). Keep the key file safe and private. Also note down the "Key Pair ID" from amazon as we will need it in the next step.

在 Python 中生成一些 URL

从 boto 2.0 版开始,似乎不支持生成签名的 CloudFront URL.Python 的标准库中不包含 RSA 加密例程,因此我们将不得不使用额外的库.我在这个例子中使用了 M2Crypto.

As of boto version 2.0 there does not seem to be any support for generating signed CloudFront URLs. Python does not include RSA encryption routines in the standard library so we will have to use an additional library. I've used M2Crypto in this example.

对于非流媒体分发,您必须使用完整的 cloudfront URL 作为资源,但是对于流媒体,我们仅使用视频文件的对象名称.有关生成仅持续 5 分钟的 URL 的完整示例,请参阅下面的代码.

For a non-streaming distribution, you must use the full cloudfront URL as the resource, however for streaming we only use the object name of the video file. See the code below for a full example of generating a URL which only lasts for 5 minutes.

此代码松散地基于 Amazon 在 CloudFront 文档中提供的 PHP 示例代码.

This code is based loosely on the PHP example code provided by Amazon in the CloudFront documentation.

from M2Crypto import EVP
import base64
import time

def aws_url_base64_encode(msg):
    msg_base64 = base64.b64encode(msg)
    msg_base64 = msg_base64.replace('+', '-')
    msg_base64 = msg_base64.replace('=', '_')
    msg_base64 = msg_base64.replace('/', '~')
    return msg_base64

def sign_string(message, priv_key_string):
    key = EVP.load_key_string(priv_key_string)
    key.reset_context(md='sha1')
    key.sign_init()
    key.sign_update(message)
    signature = key.sign_final()
    return signature

def create_url(url, encoded_signature, key_pair_id, expires):
    signed_url = "%(url)s?Expires=%(expires)s&Signature=%(encoded_signature)s&Key-Pair-Id=%(key_pair_id)s" % {
            'url':url,
            'expires':expires,
            'encoded_signature':encoded_signature,
            'key_pair_id':key_pair_id,
            }
    return signed_url

def get_canned_policy_url(url, priv_key_string, key_pair_id, expires):
    #we manually construct this policy string to ensure formatting matches signature
    canned_policy = '{"Statement":[{"Resource":"%(url)s","Condition":{"DateLessThan":{"AWS:EpochTime":%(expires)s}}}]}' % {'url':url, 'expires':expires}

    #sign the non-encoded policy
    signature = sign_string(canned_policy, priv_key_string)
    #now base64 encode the signature (URL safe as well)
    encoded_signature = aws_url_base64_encode(signature)

    #combine these into a full url
    signed_url = create_url(url, encoded_signature, key_pair_id, expires);

    return signed_url

def encode_query_param(resource):
    enc = resource
    enc = enc.replace('?', '%3F')
    enc = enc.replace('=', '%3D')
    enc = enc.replace('&', '%26')
    return enc


#Set parameters for URL
key_pair_id = "APKAIAZVIO4BQ" #from the AWS accounts CloudFront tab
priv_key_file = "cloudfront-pk.pem" #your private keypair file
# Use the FULL URL for non-streaming:
resource = "http://34254534.cloudfront.net/video.mp4"
#resource = 'video.mp4' #your resource (just object name for streaming videos)
expires = int(time.time()) + 300 #5 min

#Create the signed URL
priv_key_string = open(priv_key_file).read()
signed_url = get_canned_policy_url(resource, priv_key_string, key_pair_id, expires)

print(signed_url)

#Flash player doesn't like query params so encode them if you're using a streaming distribution
#enc_url = encode_query_param(signed_url)
#print(enc_url)

确保您使用 TrustedSigners 参数设置您的分发,该参数设置为持有您的密钥对的帐户(如果是您自己的帐户,则为Self")

Make sure that you set up your distribution with a TrustedSigners parameter set to the account holding your keypair (or "Self" if it's your own account)

请参阅开始使用安全的 AWS CloudFront使用 Python 进行流式传输 一个完整的示例,用于设置使用 Python 进行流式传输

See Getting started with secure AWS CloudFront streaming with Python for a fully worked example on setting this up for streaming with Python

这篇关于为 Amazon CloudFront 创建签名 URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆