背景
Web应用往往涉及不同页面的权限管理,对此做了如下试验,并做了一个比较好用的通用函数。
场景该Web应用涉及多个用户角色,TSG_user, TSG_admin,Plan_user,Plan_admin以及Common_user,视图函数和角色之间的对应关系大概是:
用户管理界面:Plan_admin和TSG_admin
配置界面:Plan_admin,Plan_user
查询界面:Plan_admin,Plan_user,TSG_admin,TSG_user
BS上传界面:TSG_admin,TSG_user,Plan_admin,Plan_user
Market上传界面:TSG_admin,TSG_user,Plan_admin,Plan_user
CNY_Report界面:Plan_admin,Plan_user,TSG_admin,TSG_user
CNY_Report_Result界面:Common_user
FCCY Report界面:Plan_admin,Plan_user,TSG_admin,TSG_user
需求
用高效的方式满足各视图函数对于不同角色的动作反应。
走过的坑- 用before_request装饰器: 不推荐,Before_request将在每个视图函数前执行,而每个视图函数对于权限的要求不同,如果通过endpoint去将所有视图函数的逻辑写在Before_request中也并不直观,代码也不见得简练。 还有一个原因,就是Before_request中虽然可用abort,但render的表现并不正常,会缺失样式。如果使用redirect则容易造成死循环。
从需求可以看出,变化的量仅仅是角色列表,所以考虑写一个通用函数,直接在每个视图函数头部进行调用。
函数体:
def check_auth(auth_list:list=[]):
if session.get("user_name") == None:
return render_template("404.html")
else:
if len(auth_list):
if session.get("role") in auth_list:
return None
else:
return render_template("404.html",message="Only %s can view this page!"%','.join(auth_list))
else:
return None
对函数的引用
@app.route('/',methods=["POST","GET"])
def index():
if check_auth():
return check_auth()
return redirect(url_for('query'))
@app.route('/query',methods=["POST","GET"])
def query():
if check_auth(auth_list=['Plan_admin','TSG_admin','Plan_user','TSG_user']):
return check_auth(auth_list=['Plan_admin','TSG_admin','Plan_user','TSG_user'])
注意:这里需要Return函数中返回的结果,不仅仅是直接引用函数。
思考如果存在上百个页面,并且页面和页面间的权限情况聚合性较高,那么Before_request仍然是优选方案。