tornado的权限认证之tornado.web.authenticated


如果web开发这块写一个web框架,很多时候都要用到Decorator(如果不是太清楚python的Decorator可以去找找资料看看,非常有用),例如下面的代码:

class MainHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        name = tornado.escape.xhtml_escape(self.current_user)
        self.write("Hello, " + name)

这是tornado官网上的一小段代码,代码中的tornado.web.authenticated用来对用户进行验证,如果有权限则正常调用get方法,否则抛出403禁止访问的异常。如果要写一个自己的框架,参考tornado代码中的思想是必不可少的。


tornado中的代码就不贴了,贴个自己理解后的一个测试代码,效果一样

#!/usr/bin/env python
#encoding=utf-8

import sys,os,time
import functools

def authenticated(f):
    @functools.wraps(f)
    def wrapper(self,*args,**kwargs):
        if self.get_current_user() == "admin":
            f(self,*args,**kwargs)
        else:
            raise Exception("404")
    return wrapper
class Test(object):
    def __init__(self):
        self.current_user = None
    @authenticated
    def hello(self):
        print "Hello %s" % self.get_current_user()
    def get_current_user(self):
        return self.current_user
    def set_current_user(self,user):
        self.current_user = user


if __name__ == '__main__':
    t = Test()
    t.set_current_user("admin")
    t.hello()
    t.set_current_user("me")
    t.hello()

上述代码中,重要理解的就是functools这个包里面的wraps,而要理解wraps又要理解update_wrapper和partial函数,下面就分别讲解

partial

functools. partial ( func[,*args][, **keywords] )

Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords. If more arguments are supplied to the call, they are appended to args. If additional keyword arguments are supplied, they extend and override keywords. Roughly equivalent to:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc
用中文来表达就是说partial会生成一个函数,而这个函数实际调用的是func函数,并且会将*args,**kwargs作为其参数的一部分。


update_wrapper

functools. update_wrapper ( wrapper, wrapped[, assigned][, updated] )

Update a wrapper function to look like the wrapped function. The optional arguments are tuples to specify which attributes of the original function are assigned directly to the matching attributes on the wrapper function and which attributes of the wrapper function are updated with the corresponding attributes from the original function. The default values for these arguments are the module level constantsWRAPPER_ASSIGNMENTS (which assigns to the wrapper function’s __name____module__ and __doc__, the documentation string) andWRAPPER_UPDATES (which updates the wrapper function’s __dict__, i.e. the instance dictionary).

The main intended use for this function is in decorator functions which wrap the decorated function and return the wrapper. If the wrapper function is not updated, the metadata of the returned function will reflect the wrapper definition rather than the original function definition, which is typically less than helpful.

用中文来说就是,update_wrapper会将wrapper函数中的assigned(默认是['__module__','__name__','__doc__'])属性设置为wrapped函数对应的属性,将wrapper函数的updated中的字典信息(默认是__dict__)更新为wrapped中的对应属性的信息,这样一来能够保持wrapper函数的scope信息,而不至于通过Decorator的使用之后,原函数的scope信息都变了,例如__module__、__name__等。


wraps

functools. wraps ( wrapped[, assigned][, updated] )

This is a convenience function for invoking update_wrapper() as a function decorator when defining a wrapper function. It is equivalent topartial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated). For example:

也就是返回一个partial函数返回的对象,而这个对象以update_wrapper为根本,并且设置后面的一些参数,例如wrapped、assigned、updated等。这样一来,当使用@functools.wraps的时候就会将被装饰的函数作为update_wrapper中的wrapper参数调用。


后面说的这些是不影响功能的,也就是说最开始的那个测试代码中即使注释掉@functools.wraps一行也可以运行。但是利用后面的这些函数只是为了保证代码的意义清晰。

参考csdn上的一篇

参考官网functools


你可能感兴趣的:(python)