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
每天进步一点,加油!