美文网首页
Flask实战2-用户角色

Flask实战2-用户角色

作者: 猴子精h | 来源:发表于2017-09-27 00:40 被阅读143次

    本示例中有三种权限角色:匿名,普通用户,管理员,内容管理员(权限介于用户和管理员之间,可以修改上传文章的内容)

    定于roles模型

    class Role(db.Model):
        __tablename__ = 'roles'
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True, index=True)
        # 只有一个角色需要设置为true,用户注册时,其角色会被设置成默认
        default = db.Column(db.Boolean, default=False, index=True)
        permissions = db.Column(db.Integer)
        user = db.relationship('User', backref='role', lazy='dynamic')
    

    permission类型为整型,表示位标志。各种操作都对应一位,程序权限:

    操作 位值 说明
    关注用户 0b00000001 (0x01)
    发表评论 0b00000010 (0x02)
    写文章 0b00000100 (0x04)
    管理评论 0b000001000 (0x08)
    管理员权限 0b10000000 (0x80)

    为方便使用,在模型中常量保存:

    class Permission:
        FOLLOW = 0x01
        COMMENT = 0x02
        WRITE_ARTICLES = 0x04
        MODERATE_COMMENTS = 0x08
        ADMINISTER = 0x80
    

    根据上面的权限位,可有得出各个角色使用的权限位,在验证权限时则使用与运算即可;

    角色名 权限 说明
    匿名 0b00000001 (0x00) 未登入,仅有阅读权限
    用户 0b00000111 (0x07) 具有发布文章,发表评论和关注其他用户,默认角色
    内容管理员 0b00001111 (0x0f)
    管理员 0b11111111 (0xff)

    在角色类中添加一个快速新建角色的方法。注意:'匿名'角色不需要在数据库中表示,这个角色的作用就是为了表示不在数据库中的用户。

    class Role(db.Model):
        ...
        
        @staticmethod
        def insert_roles():
            roles = {
                'User': (Permission.FOLLOW | Permission.COMMENT | Permission.WRITE_ARTICLES, True),
                'Moderator': (Permission.FOLLOW | Permission.COMMENT | Permission.WRITE_ARTICLES | Permission.MODERATE_COMMENTS, False),
                'Administrator': (0xff, False)
            }
            for r in roles:
                role = Role.query.filter_by(name=r).first()
                if role is None:
                    role = Role(name=r)
                print roles[r][0]
                role.permissions = roles[r][0]
                role.default = roles[r][1]
                db.session.add(role)
            db.session.commit()
        
    # Use
    python manage shell
    
    Role.insert_roles()
    

    角色验证

    为了简化角色和权限的实现过程,我们可在User模型中添加一个辅助的方法,检查是否有制定的权限:

    class User(UserMixin, db.Model):
        ...
        # 与运算验证权限
        def can(self, permissions):
            return self.role not None and (self.role.permissions & permissions == permissions)
            
        def is_administrator(self):
            return self.can(Permission.ADMINISTER)
            
    
    # 出于一致性考虑,这里还定义了AnonymousUser类,继承Flask-Login的AnonymousUserMixin类
    class AnonymousUser(AnonymousUserMixin):
        def can(self, permissions):
            return False
    
        def is_administator(self):
            return False
    
    # 将其设为用户未登录时的current_user值, 这样程序不用先检查用户是否已经登入
    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)
        
    # 使用
    @main.route('/admin')
    @login_required
    @admin_required
    def for_admin_only():
        return "For administrator"
        
    @main.route('/moderator')
    @login_required
    @permission_required(Permission.MODERATE_COMMENTS)
    def for_moderators_only():
        return "For comment moderators."
    

    另外,为了模版中也可以全局使用Permission类,使用上下文管理器,能让变量在所有模版中全局访问

    @main.app_context_processor
    def inject_permission():
        return dict(Permission=Permission)
    

    相关文章

      网友评论

          本文标题:Flask实战2-用户角色

          本文链接:https://www.haomeiwen.com/subject/sbhyextx.html