Auth
- 基于角色的访问权限控制
- 有的管理员只能访问日志,而有的能访问会员列表,有的管理电影
- 这部分还属于admin
- 从创建表单模型开始,别着急
class AuthForm(FlaskForm): """访问权限控制""" name = StringField( label='权限名称', validators=[ DataRequired("请输入权限名称!") ], description="权限", render_kw={ "class": "form-control", "placeholder": "请输入权限名称!" } ) url = SubmitField( label="权限地址", validators=[ DataRequired("请输入权限地址!") ], description="权限地址", render_kw={ "class": "btn btn-primary", "placeholder": "请输入权限地址!" } ) submit = SubmitField( label="添加", render_kw={ "class": "btn btn-primary" } )
- 定义视图,注意要指定GET/POST方法
- 这就很明显了,name字段存储操作的名称,url是这个操作在view中定义的访问路径
- 访问权限控制就是限制能访问的url
- 删除编辑查看等操作,与之前同理
Role
- 给角色赋予权限
- 表单模型,这里使用到多选
class RoleForm(FlaskForm): """管理员角色""" name = StringField( label='角色名称', validators=[ DataRequired("请输入角色名称!") ], description="角色", render_kw={ "class": "form-control", "placeholder": "请输入角色名称!" } ) auth = SelectMultipleField( label="权限列表", validators=[ DataRequired("请选择权限") ], coerce=int, # 选择之后,会将id返回 choices=[(v.id, v.name) for v in auths], description="权限列表", render_kw={ "class": "form-control", } ) submit = SubmitField( label="添加", render_kw={ "class": "btn btn-primary" } )
- 角色只是给管理员的一顶帽子,最终的限定还是通过装饰器关联Auth和Admin
- 列表、删除和编辑
Admin
- 给管理员赋予角色,这里使用到关联查询和if判断超管
class AdminForm(FlaskForm): """管理员管理""" name = StringField( label='管理员名称', validators=[ DataRequired("请输入管理员名称!") ], description="管理员", render_kw={ "class": "form-control", "placeholder": "请输入管理员名称!" } ) pwd = PasswordField( label="管理员密码", validators=[ DataRequired("请设置管理员密码") ], description="管理员密码", render_kw={ "class": "form-control", "placeholder": "请输入管理员密码" } ) repwd = PasswordField( label="重复管理员密码", validators=[ DataRequired("请重复管理员密码"), EqualTo('pwd', message="两次密码不一致!") ], description="重复管理员密码", render_kw={ "class": "form-control", "placeholder": "请重复管理员密码" } ) # 最好跟数据库的字段名保持一致 role_id = SelectField( label="角色列表", validators=[ DataRequired("请选择角色") ], # 选择之后,会将id以列表返回 choices=[(v.id, v.name) for v in roles], description="角色列表", render_kw={ "class": "form-control", } ) is_super = SelectField( label="是否为超级管理员", validators=[ DataRequired("0:是 1:不是") ], description="是否设置为超级管理员", coerce=int, choices=[v for v in (0,1)], render_kw={ "class": "form-control", "id": "input_is_super_id" } ) submit = SubmitField( label="编辑", render_kw={ "class": "btn btn-primary" } )
# 管理员列表 @admin.route('/admin/list/<int:page>', methods=["GET"]) @admin_login def admin_list(page=None): if page is None: page = 1 # 关联表的数据以 表名.字段 获取 page_data = Admin.query.join( Role ).filter( Role.id == Admin.role_id ).order_by( Admin.addtime.desc() ).paginate(page=page, per_page=3) return render_template('admin/adminlist.html', page_data=page_data)
- 最终超管只通过
is_super
字段确定,role_id不起作用{% if v.is_super==0 %} <td>超级管理员</td> {% else %} <td>普通管理员</td> {% endif %}
权限控制
- 权限——角色——管理员,最终需要使用装饰器,查询出当前登录管理员所拥有权限,限制访问
- 超管使用角色,授权各管理员
- 管理员登录后,会经过装饰器,根据admin表中授权的角色,限制访问路径
- 超管授权存储在
admin
表,所以最终在这里查询# 权限控制装饰器 def admin_auth(func): @wraps(func) def dec_func(*args, **kwargs): admin = Admin.query.join( Role ).filter( # 当前登录对象 Admin.id == session["admin_id"], # 被授权的角色 Role.id == Admin.role_id ).first() auths = admin.role.auths # 获取可访问路径 auths = list(map(lambda v:str(v), auths.split(","))) # 权限id print(auths) # 将授权路径搞到列表中 auth_urls = Auth.query.all() urls = [v.url for v in auth_urls for val in auths if int(val)==v.id] # 嵌套for循环,最终if判断 rule = str(request.url_rule) # 请求的路径 print(urls) print(rule) # 这个多了个/admin,在哪定义? # 限制访问: if rule[6:] not in urls:# 先使用截取的办法实现功能 abort(404) return func(*args, **kwargs) return dec_func
- 根据
role
表中的授权情况,即可限制管理员访问!
- 根据
- 如何初始化定义超管的权限?可以通过直接在数据库中添加所有角色实现