为Amazon CloudFront创建签名的Cookie

为Amazon CloudFront创建签名的Cookie,第1张

为Amazon CloudFront创建签名的Cookie

我创建了一个boto功能请求以添加此功能,但与此同时,我将其与django
python应用程序配合使用。这是我自己生成的简单代码。底部是django视图的示例方法,因此您可以看到如何为包含Cloudfront内容的网页设置cookie。

import timefrom boto.cloudfront import CloudFrontConnectionfrom boto.cloudfront.distribution import Distributionfrom config import settingsimport loggingfrom django.template.context import RequestContextfrom django.shortcuts import render_to_responselogger = logging.getLogger('boto')logger.setLevel(logging.CRITICAL) #disable DEBUG logging that's enabled in AWS by default (outside of django)AWS_ACCESS_KEY="AKABCDE1235ABCDEF22A"#SAMPLEAWS_SECRET_KEY="a1wd2sD1A/GS8qggkXK1u8kHlh+BiLp0C3nBJ2wW" #SAMPLEkey_pair_id="APKABCDEF123ABCDEFAG" #SAMPLEDOWNLOAD_DIST_ID = "E1ABCDEF3ABCDE" #SAMPLE replace with the ID of your Cloudfront dist from Cloudfront console############################################def generate_signed_cookies(resource,expire_minutes=5):    """    @resource   path to s3 object inside bucket(or a wildcard path,e.g. '/blah/*' or  '*')    @expire_minutes     how many minutes before we expire these access credentials (within cookie)    return tuple of domain used in resource URL & dict of name=>value cookies    """    if not resource:        resource = 'images/*'    dist_id = DOWNLOAD_DIST_ID    conn = CloudFrontConnection(AWS_ACCESS_KEY, AWS_SECRET_KEY)    dist = SignedcookiedCloudfrontDistribution(conn,dist_id)    return dist.create_signed_cookies(resource,expire_minutes=expire_minutes)############################################class SignedcookiedCloudfrontDistribution():    def __init__(self,connection,download_dist_id,cname=True):        """        @download_dist_id   id of your Cloudfront download distribution        @cname          boolean True to use first domain cname, False to use   cloudfront domain name, defaults to cname  which presumably matches your writeable cookies ( .mydomain.com)        """        self.download_dist = None        self.domain = None        try: download_dist = connection.get_distribution_info(download_dist_id) if cname and download_dist.config.cnames:     self.domain = download_dist.config.cnames[0] #use first cname if defined else:     self.domain = download_dist.domain_name self.download_dist = download_dist        except Exception, ex: logging.error(ex)    def get_http_resource_url(self,resource=None,secure=False):        """        @resource   optional path and/or filename to the resource         (e.g. /mydir/somefile.txt);         defaults to wildcard if unset '*'        @secure     whether to use https or http protocol for Cloudfront URL - updateto match your distribution settings         return constructed URL        """        if not resource: resource = '*'        protocol = "http" if not secure else "https"        http_resource = '%s://%s/%s' % (protocol,self.domain,resource)        return http_resource    def create_signed_cookies(self,resource,expire_minutes=3):        """        generate the Cloudfront download distirbution signed cookies        @resource   path to the file, path, or wildcard pattern to generate policy for        @expire_minutes  number of minutes until expiration        return      tuple with domain used within policy (so it matches          cookie domain), and dict of cloudfront cookies you         should set in request header        """        http_resource = self.get_http_resource_url(resource,secure=False)    #per-file access #NOTE secure should match security settings of cloudfront distribution    #    http_resource = self.get_http_resource_url("somedir/*")  #blanket access to all /somedir files inside my bucket    #    http_resource = self.get_http_resource_url("*")          #blanket access to all files inside my bucket        #generate no-whitespace json policy, then base64 enpre & make url safe        policy = Distribution._canned_policy(http_resource,SignedcookiedCloudfrontDistribution.get_expires(expire_minutes))        enpred_policy = Distribution._url_base64_enpre(policy)        #assemble the 3 Cloudfront cookies        signature = SignedcookiedCloudfrontDistribution.generate_signature(policy,private_key_file=settings.AMAZON_PRIV_KEY_FILE)        cookies = { "CloudFront-Policy" :enpred_policy, "CloudFront-Signature" :signature, "CloudFront-Key-Pair-Id" :key_pair_id #e.g, APKA..... -> same value you use when you sign URLs with boto distribution.create_signed_url() function        }        return self.domain,cookies    @staticmethod    def get_expires(minutes):        unixTime = time.time() + (minutes * 60)        expires = int(unixTime)  #if not converted to int causes Malformed Policy error and has 2 decimals in value        return expires    @staticmethod    def generate_signature(policy,private_key_file=None):        """        @policy     no-whitespace json str (NOT enpred yet)        @private_key_file   your .pem file with which to sign the policy        return enpred signature for use in cookie        """        #sign the policy - pre borrowed from Distribution._create_signing_params()        signature = Distribution._sign_string(policy, private_key_file)        #now base64 enpre the signature & make URL safe        enpred_signature = Distribution._url_base64_enpre(signature)        return enpred_signature############################################def sample_django_view_method(request,template="mytemplate.html"):    expireLen = 30 #30 minutes    s3resource = "somepath_in_my_bucket/afile.mp4"    context = {} #variables I'm passing to my html template    response = render_to_response(template, context, context_instance=RequestContext(request))    domain,cookies = generate_signed_cookies(s3resource,expire_minutes=expireLen)    #TROUBLESHOOTING cookieS:    #NOTE - cookie Domain must be a domain you control that spans your app & your Cloudfront CNAME    #NOTE - (e.g. if my webapp is www.mydomain.com and my AWS Download Distribution has cname cloud.mydomain.com, cant set cookies from webapp to  # www.mydomain.com or localhost.mydomain.com or cloud.mydomain.com and have them work         # -> instead set cookies to .mydomain.com to work across sub-domains, you can then verify in request headers to CloudFront that these cookies get passed.        # TIP - if you set_cookies from a page with a .mydomain.com suffix, but don't see them get set in Chrome they didn't get set because of permissions - can't set to a diff subdomain or diff base domain        # TIP - if you set_cookies and see them in Chrome but don't see them in request headers to Cloudfront, cookie domain is likely too narrow, need to widen to span subdomains    base_domain = '.mydomain.com'    # NOTE: Sanity check when testing so you can flag any gotchas - I have not fully tested using non-cname urls inside policy vs all possible domains for cookie itself       if not domain.endswith(base_domain):        logger.warn("This likely won't work - your resource permissions use a different domain than your cookies")    for name,value in cookies.items():        response.set_cookie(name,value=value,httponly=True,domain=base_domain)    return response############################################if __name__ == '__main__':    domain,cookies = generate_signed_cookies('images/*',expire_minutes=30)

关于我的设置的注意事项:

  • 我只需要对已经设置并可以用于签名URL的下载分发进行一项更改:我必须添加一个具有与我的网站匹配的基本域的cname。
  • 我使用了Chrome Web Developer工具:

    • 网络:查看在Cloudfront呼叫中发送的请求标头,并查看403 vs 200 /状态/响应大小
    • 控制台:看到403错误,直到一切正常
    • 资源> cookie-验证[localhost或您的主机] .mydomain.com cookie是否显示了填充的3个Cloudfront cookie,它们是否设置为Domain = .mydomain.com,并且这些值与Cloudfront的请求标头中的值匹配(如果丢失,可能是域配置错误)

我的AWS配置

  • S3需要Cloudfront起源
  • Cloudfront下载分布:
    • 分布设置:
    • cname定义:cloud.mydomain.com(对我来说是新的!)
    • 默认的Cloudfront证书
    • 来源标签:定义了1个可映射到我的S3存储桶的来源
    • 行为标签-默认:
    • 所有这些都与我已经使用签名URL的设置相同
    • HTTP和HTTPS
    • 转发标题:无
    • 使用原始缓存头
    • 最小TTL:0
    • 转发cookie:无
    • 转发查询字符串:否
    • 流畅串流:否
    • 限制查看者访问权限:是(自已签名的URL以来没有更改)
    • 受信任的签名者:自我

拥有上述cookie生成代码后,最棘手的部分是:

  • 确保cookie域正确
  • 确保策略中的路径/资源与从您的应用发出的请求匹配


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5673570.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存