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

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

问题描述

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

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应用程序,以防止它

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,我相信Amazon 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专家,而且绝对不知道如何正确创建Signed 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)

请参见使用Python安全AWS CloudFront流传输入门,以获取有关将其设置为流式传输的完整示例使用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天全站免登陆