35、Flask实战第35天:权限设计

二进制及其相关运算

认识二进制

0,1,2,3,4,5,6,7,8,9,10:逢10进1
0,1:逢2进1

二进制转十进制

十进制 二进制
0 0
1 1
2 10
3 11
4 100
255 11111111

二进制之间的与(&)或(|)运算

与运算:0&1=0 1&1=1 相当于python if条件中的and
或运算:0|1=1 0|0=0 相当于Python if条件中的or

判断某个用户有没有某个权限(a)

只要将需要对比的用户的权限和a权限的二进制码进行与运算,如果得到的结果和a相等,那么就代表这个用户有a这个权限,否则代表没有

 

权限和角色模型定义

用户是和角色绑定,而不是直接拥有权限,通过角色拥有的权限,则该用户就拥有什么权限

一个用户可以同时拥有多个角色(如:运营和销售),一个角色也可以对应多个用户,因此用户和角色是多对多的关系

权限,这里直接用类固定写好。

配置模型,编辑cms.modles.py

定义一个权限的类

class CMSPersmission(object):
    #255的二进制方式表示11111111
    ALL_PERMISSION = 0b11111111
    #访问者权限
    VISITOR =        0b00000001
    #管理帖子权限
    POSTER =         0b00000010
    #管理评论的权限
    COMMENTER =      0b00000100
    #管理板块的权限
    BOARDER =        0b00001000
    #管理前台用户的权限
    FRONTUSER =      0b00010000
    #管理后台用户的权限
    CMSUSER =        0b00100000
    #管理后台管理员的权限
    ADMIN =          0b01000000

定义角色模型并且和CMSUser模型组成多对多的关系

cms_role_user = db.Table(
    'cms_role_user',
    db.Column('cms_role_id', db.Integer, db.ForeignKey('cms_role.id'), primary_key=True),
    db.Column('cms_user_id', db.Integer, db.ForeignKey('cms_user.id'), primary_key=True)
)

class CMSRole(db.Model):
    __tablename__ = 'cms_role'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), nullable=False)
    desc = db.Column(db.String(200), nullable=True)
    create_time = db.Column(db.DateTime, default=datetime.now)
    permissions = db.Column(db.Integer, default=CMSPersmission.VISITOR)

    users = db.relationship('CMSUser', secondary=cms_role_user, backref='roles')

编辑CMSUser模型,该用户拥有的权限,是否拥有某权限,是不是开发者(拥有所有权限)

class CMSUser(db.Model):
    __tablename__ = 'cms_user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(50), nullable=False)
    _password = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(50), nullable=False, unique=True) #unique表示必须是唯一的
    join_time = db.Column(db.DateTime, default=datetime.now)

    def __init__(self, username, password, email):
        self.username = username
        self.password = password
        self.email = email

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, raw_password):
        self._password = generate_password_hash(raw_password)

    def check_password(self, raw_password):
        result = check_password_hash(self.password, raw_password)
        return result

    @property
    def permissions(self):
        # 如果该用户没有任何角色,则没有权限
        if not self.roles:
            return 0
        #遍历该用户拥有的角色,获取该角色权限,并所有所含所有角色权限通过或运算组合在一起
        all_permissions = 0
        for role in self.roles:
            permissions = role.permissions
            all_permissions |= permissions
        return all_permissions

    def has_permission(self, permission):
        # 把传过来的权限和该用户所拥有的权限进行与运算,得出的结果和传过来的权限进行比较,一致的话则拥有该权限
        #  0b00000011 & 0b00000001 ---->1 (0b00000001)
        return self.permissions & permission == permission
    
    @property
    def is_developer(self):
        #判断该用户是否是开发者,开发者拥有所有权限
        return self.has_permission(CMSPersmission.ALL_PERMISSION)

映射表到数据库

python manage.py db migrate
python manage.py db upgrade

 

创建角色,并把用户加入到角色

编辑manage.py

...
CMSRole = cms_models.CMSRole
CMSPermission = cms_models.CMSPersmission

@manager.command
def create_role():
    #访问者(可以修改个人信息)
    visitor = CMSRole(name='访问者',desc='可以修改个人信息')
    visitor.permissions = CMSPermission.VISITOR

    #运营角色(修改个人信息,管理帖子,管理评论,管理前台用户)
    operator = CMSRole(name='运营', desc='管理帖子,评论,前台用户')
    operator.permissions = (CMSPermission.VISITOR|
                            CMSPermission.POSTER|
                            CMSPermission.COMMENTER|
                            CMSPermission.FRONTUSER)
    #管理员(拥有绝大部分权限)
    admin = CMSRole(name='管理员', desc='拥有本系统所有权限')
    admin.permissions = (CMSPermission.VISITOR|
                         CMSPermission.POSTER|
                         CMSPermission.COMMENTER|
                         CMSPermission.BOARDER|
                         CMSPermission.FRONTUSER|
                         CMSPermission.CMSUSER)
    #开发者
    developer = CMSRole(name='开发者', desc='开发人员专用')
    developer.permissions = CMSPermission.ALL_PERMISSION

    db.session.add_all([visitor, operator, admin, developer])
    db.session.commit()

@manager.option('-e', '--email', dest='email')
@manager.option('-n', '--name', dest='nmae')
def add_user_to_rule(email, name):
    user = CMSUser.query.filter_by(email=email).first()
    if user:
        role = CMSRole.query.filter_by(name=name).first()
        if role:
            role.users.append(user)
            db.session.commit()
            print('用户{}添加到角色{}成功'.format(email, name))
        else:
            print('没有这个角色:{}'.format(name))
    else:
        print('没有这个用户:{}'.format(email))

@manager.command
def test_permission():
    user = CMSUser.query.first()  #目前我数据库只有一个账号
    if user.is_developer:
        print('用户{}有开发者的权限'.format(user.email))
    else:
        print('用户{}没有开发权限'.format(user.email))

执行创建角色

python manage.py create_role

 

posted @ 2018-08-11 08:17  sellsa  阅读(1221)  评论(0编辑  收藏  举报