在Flask中有Flask-Login这个插件可以帮我们实现用户登录权限管理管理,但是也仅仅是对登录和未登录做了区分校验。对于一个成熟的web系统来说不但有会员系统,还应该对会员的等级做出详细的划分,权限低的会员无法使用权限高的接口,我把这个成为会员的权限等级管理。
Flask-Login只能区分会员登录与未登录的状态,不能对登录成功后的等级做区分。为了实现这个功能就需要我们自己手动造轮子,当然Flask-Login已经完善的登录管理可以很方便的帮助我们完成轮子的制造。我们的权限管理完全是建立在Flask-Login插件之上的,需要用这个插件完成登录状态校验然后实现权限级别。
对于Flask-Login而言,当我们把这个插件集成在我们的项目中之后,我们可以轻松的使用@login_required这个装饰器给视图函数加上登录保护。在login_required这个逻辑约束下,登录过的用户才能跳转到视图函数内部,否则Flask-Login就会abort一个401的错误状态码,或者重定向到我们定义好的登录视图函数。
Flask-Level的实现思路
受到Flask-Login的模式启发,我准备写一个Flask-Level插件,当然这个插件要足够简单,不然复杂的业务逻辑我也不会写。模仿着Flask-Login我们的插件也要有一个装饰器@level_limit(level=1)用来限制接口权限,参数level是用来声明接口等级。满足level等级的用户允许进入视图函数内部,否则就abort一个403的错误状态码。
为了实现level的判断需要给用户模型添加一个limit_level字段,这个字段用来表示用户拥有的权限等级,类型是一个smallint类型,毕竟权限等级不会划分太多层,当然要有一个默认值,默认值为0表示无权限限制,当然如果这个接口是所有用户都能访问的话那么大可不必给他加上权限限制的装饰器,多此一举而且会降低系统的速度。
我们可以手动的添加给用户model添加字段,但是为了使我们的Flask-Level显得更像那么回事,需要定义一个Model父类BaseLevel。这个类没有其他作用只是添加了一个limit_level的column,子类只需要继承这个父类的话就可以自动继承这个字段,省去自己定义的麻烦啦。
Flask-Login已经通过代理模式帮我们实现了一个current_user,如果账号已经登录成功的话我们就可以在Flask上下文环境中使用这个变量。变量里存储的事当前登录用户的相关信息,可以方便的获取到用户的权限等级,极大的简化了我们的业务代码量。
代码实现
我把这种实现叫做接口级别的权限保护,因为权限保护的是整个视图函数,当然这个词并不是我发明的,这是有次我在GitHub看SpringBoot项目的时候作者用到的一个词,我觉得很唬人我就给学来了。总是功能的实现十分简陋和粗糙,只是做学习使用,有需要的同学可以自己完善,这里只是阐述我的思路。
from functools import wraps from flask import current_app, redirect, url_for, abort from flask_login import current_user from sqlalchemy import SmallInteger, Column class FlaskLevel(): def __init__(self): self.limited_view = None self.limited_message = "请求被终止,您无权访问该接口" def init_app(self, app): app.limit_level = self class BaseLevel(): limit_level = Column(SmallInteger, default=0) def level_limit(level=0): def decorater(func): @wraps(func) def wrapper(*args, **kwargs): if current_user.limit_level >= level: return func(*args, **kwargs) elif current_app.limit_level.limited_view: return redirect(url_for(current_app.limit_level.limited_view)) else: abort(403) return wrapper return decorater
完整介绍我放在Github了:https://github.com/weiney。感兴趣的同学可以克隆一份自己运行一下,核心代码是在/app/libs/flask_level.py下面。我已经写了简单的实例,感兴趣的可以自行研究,都是一些没有质量的代码,也是记录自己慢慢学习的过程。
总结
本文的实现主要是借助装饰器和第三方插件的耦合实现的,如果没有Flask-Login这么好的插件的话开发起来绝对没有这么简单。另外说一嘴,Python装饰器可以说是我用到的最多也是最有用的Python高阶语法,所以不懂的朋友一定要把装饰器给理解清楚哦!
最后祝我早日找到工作,好挣钱养活自己,加油加油,老天保佑!!!
共有 0 条评论