角色在数据库中的表示
class Permission: # 权限常量 FOLLOW = 0x01 # 关注用户 COMMENT = 0x02 # 发表评论 WRITE_ARTICLES = 0x04 # 写文章 MODERATE_COMMENTS =0x08 # 管理他们发表的评价 ADMINISTER = 0x80 # 管理员权限 class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) default = db.Column(db.Boolean, default=False, index=True) permissions = db.Column(db.Integer) users = db.relationship('User', backref='role') def __init__(self, **kwargs): # 初始化角色权限 super(Role, self).__init__(**kwargs) if self.permissions is None: self.permissions = 0 @staticmethod # # 静态方法无需实例化 def insert_roles(): roles = { # 角色名对应权限 'User' : [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE_ARTICLES], 'Moderator': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE_ARTICLES, Permission.MODERATE_COMMENTS], 'Administrator' : [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE_ARTICLES, Permission.MODERATE_COMMENTS, Permission.ADMINISTER] } default_role = 'User' for r in roles: # 通过角色查找现有角色去设置权限,方便修改权限和添加新角色 role = Role.query.filter_by(name = r).first() if role is None: # 当数据库中没有某个角色时创建个新角色 role = Role(name=r) role.reset_permissions() for perm in roles[r]: role.add_permission(perm) role.default = (role.name == default_role) # 判断是不是默认用户 db.session.add(role) db.session.commit() def has_permission(self, perm): # 判断当前角色是否已经有该权限 return self.permissions & perm == perm def add_permission(self, perm): # 角色添加权限 if not self.has_permission(perm): self.permissions += perm def remove_permiss(self, perm): # 角色删除权限 if self.has_permission(perm): self.permissions -= perm def reset_permissions(self): # 重置角色 self.permissions = 0 def __repr__(self): return '<Role %r>' % self.name
用户赋予角色和验证
class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(64), unique=True, index=True) username = db.Column(db.String(64), unique=True, index=True) password_hash = db.Column(db.String(128)) confirmed = db.Column(db.Boolean, default=False) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) def __init__(self, **kwargs): # 初始化用户角色 super(User, self).__init__(**kwargs) if self.role is None: if self.email == current_app.config['FLASKY_ADMIN']: # 管理员用户邮箱的匹配 self.role = Role.query.filter_by(name='Administrator').first() else: # 否则都是默认用户 self.role = Role.query.filter_by(default=True).first() def can(self, permissions): # 检测是否含有指定权限 return self.role is None and (self.role.permissions & permissions) == permissions def is_administrator(self): # 检测是否含有所有权限,即是否是管理员 return self.can(Permission.ADMINISTER) class AnonymousUser(AnonymousUserMixin): # 重写匿名用户,为保持与其他用户一致性 def can(self, permissions): return False def is_administrator(self): return False login_manager.anonymous_user = AnonymousUser
检查用户权限的自定义装饰器
from functools import wraps from flask import abort from flask_login import current_user from .models import Permission def permission_required(permission): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.can(permission): abort(403) return f(*args, **kwargs) return decorated_function return decorator def admin_required(f): return permission_required(Permission.ADMINISTER)(f)
有关于装饰器和@wraps的知识链接:https://www.cnblogs.com/Neeo/p/8371826.html
自定义装饰器的使用
@main.route('/moderate') @login_required @permission_required(Permission.MODERATE_COMMENTS) def moderate_test(): return "Just for test!"