tornado简单权限认证

工作中遇到需要权限认证的需求,想到两个方法,在此记录

方法一:

用类装饰器,如下:

class authenticated(object):
    def __init__(self, role):
        self.role = role

    def __call__(self, method):
        def login_wrapper(_self, *args, **kwargs):
            userinfo = _self.current_user
            print(userinfo)
            if userinfo:
                return method(_self, *args, **kwargs)
            return _self.redirect(_self.get_login_url())

        def admin_wrapper(_self, *args, **kwargs):
            userinfo = _self.current_user
            user_obj = User.query.filter_by(name=userinfo).first()
            print(type(int(user_obj.grade)))
            if userinfo and user_obj.grade == '1':
                return method(_self, *args, **kwargs)
            return _self.write("You have no access!")

        def guest_wrapper(_self, *args, **kwargs):
            userinfo = _self.current_user
            user_obj = User.query.filter_by(name=userinfo).first()
            if userinfo and user_obj.grade == '2':
                return method(_self, *args, **kwargs)
            return _self.write("You have no access!")

        wrapper = dict(admin=admin_wrapper, guest=guest_wrapper)
        return wrapper[self.role]

这种方法是简单的权限认证,将权限分为几个角色,使用的时候只需要指定角色就可以,在这里是将权限分为几个等级,如上:grade 1,grade 2等等

例:

class ExampleHandler(RequestHandler):
    @authenticated(1)
    def get(self):
        self.write("

This is an example

"
)

例子所示这块代码的意思是,只有等级为1的用户才可以执行get方法,其他不是1的用户如果访问会显示You have no access!这是简单的权限认证

方法二:

但是在实际应用中并不会如此简单,经常发生的情况是,我需要某个用户在某个URL上有某个权限,这种情况就比较复杂了,方法一中的权限角色就已经不能满足需求了,那么应该怎么办呢?

可以试想下面的思路:如果我能拦截到前端过来的URL和方法,那么在进入get、post等方法之前就把请求拦截下来,在此之前对请求进行分析,权限认证,就会方便很多,这里就用到了tornado的一些方法,比如如何拦截请求,如何获取当前用户
以下是我的代码:

    def prepare(self):
        url_id = Url.query.filter_by(url=self.request.uri.split("?")[0]).first().id
        usr = User.query.filter_by(name=self.current_user).first()
        if usr is None:
            return
        method = self.request.method
        if method == "GET":
            if url_id not in eval(usr.read):
                if self.request.headers.get("X-Requested-With", None):
                    self.finish({"auth": "权限不够"})
                else:
                    self.write("")
                    self.finish()

        if method == "POST":
            if url_id not in eval(usr.write):
                if self.request.headers.get("X-Requested-With", None):
                    self.finish({"auth": "权限不够"})
                else:
                    self.write("")
                    self.finish()

        if method == "DELETE":
            if url_id not in eval(usr.delete):
                if self.request.headers.get("X-Requested-With", None):
                    self.finish({"auth": "权限不够"})
                else:
                    self.write("")
                    self.finish()

在此解释下代码中的相关东西,首先Url和User是数据库中url和用户对应的表,每个用户对应的增删改查权限写入对应的URL的ID,取决于自己的规划,在此重点说逻辑上的思路,

应该说tornado中涉及到请求的数据都可以在self.request中找到,可以自己打印出来看看,具体有什么参数可以在request里面拿到呢,附上链接,点击可以看到完整的属性列表,
X-Requested-With是用来检查是否是ajax传输,如果是ajax的话就返回json数据,前端alert以下,否则就在网页中写入一个javascript脚本,弹出“权限不够“并返回上一个页面,这是服务器端完整的思路。

至于前端页面也应该有相关的验证,如果没有某一个页面的访问权限,则在前端页面不显示此链接入口,如果是删除或提交表单等操作,则相关按钮应设置为不可点击。具体细节不再赘述。

以上。

你可能感兴趣的:(tornado,python)