zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    MPLab X 配置字的设置
    System.Windows.Forms.Timer定时器的“自毁”
    单片机部分缩写对照
    我的艰辛之路——2012年个人总结之三
    浏览器IE6不支持的CSS样式的选择符[转]
    SVN 用户权限管理[转]
    VC++ 随机数生成方案选择[转]
    GB/T 77142005参考文献规范[转]
    正则表达式备忘[转]
    文档、视图、框架窗口、文档模板之间的相互关系【转】
  • 原文地址:https://www.cnblogs.com/sellsa/p/9458451.html
Copyright © 2011-2022 走看看