文章目录
- Auth
- Role
- Admin
- 权限控制
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(","))) # 权限idprint(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
表中的授权情况,即可限制管理员访问!
- 根据
- 如何初始化定义超管的权限?可以通过直接在数据库中添加所有角色实现