二进制权限

本文介绍了一种使用二进制权限管理的RBAC(Role-Based Access Control)系统,通过位运算简化权限分配和鉴权过程。代码示例展示了如何创建数据库表、进行权限操作以及实现用户与角色的多对多关系。该系统减少了传统RBAC所需的资源表,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

普通rbac


用户  角色    角色资源表   资源

二进制权限

用户表  
张三   1
角色表  
id     名称       resource(int)
1     总经理          7

资源表         resource(int)
1  添加用户       1
2  添加部门       2 
3  订单管理       4
4  用户管理       8
5  产品管理       16

基本原理

位&运算 :对比权限

位 | 运算 :添加权限

异或 ^:删除权限

可见用二进制权限比普通的rbac少一张表

建表

这里用户表省略

class Role(db.Model):
    __tablename__ = "role"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    resource = db.Column(db.Integer)


class Resourse(db.Model):
    __tablename__ = 'rosourse'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    resource = db.Column(db.Integer)

原生sql

import pymysql
import threading
lock = threading.Lock()



class DB:
    def __init__(self) -> None:
        self.conn = pymysql.connect(host='localhost',port=3306,user='root',password='2743655496',db='social',cursorclass=pymysql.cursors.DictCursor)
        self.cursor = self.conn.cursor()

    def reConnect(self):
        try:
                self.conn.ping()
        except:
                self.conn()

    #更新添加
    def update(self,sql):
            self.cursor.execute(sql)
            # self.conn.commit()

    #获取一条
    def findOne(self,sql):
            self.cursor.execute(sql)
            res = self.cursor.fetchone()
            return res
    #获取多条
    def findAll(self,sql):
            self.reConnect()
            lock.acquire()
            self.cursor.execute(sql)
            res = self.cursor.fetchall()
            lock.release()
            return res

#     提交方法
    def commit(self):
        self.conn.commit()
#     回滚方法
    def rollback(self):
        self.conn.rollback()


db1 = DB()

 用户表和角色表一对一(此例子中的表和刚刚创的表无关,仅参考代码)

# 封装二进制角色权限管理
from common.util.db import db1


class BinPro:
    # 给角色授权,添加资源
    def set_permission(self, role_id, resource_ids):
        print('参数》》》》', role_id, resource_ids, type(eval(resource_ids)))
        for resource_id in eval(resource_ids):
            # 通过资源id获取资源的二进制权限
            sql = "select * from resources where id=%d" % (int(resource_id))
            res = db1.get_one(sql)
            resource = res['resources_id']
            print('resource>>>>>', resource)
            # 根据角色id更新角色的二进制权限
            sql1 = "select * from role where id=%d" % (int(role_id))
            res1 = db1.get_one(sql1)
            role = res1['resources_id']
            print('role>>>>>', role)
            # 二进制位运算位或 |  添加
            res2 = resource | role
            print('res2>>>>', res2)
            sql3 = "update role set resources_id=%d where id=%d" % (int(res2), int(role_id))
            db1.update(sql3)
        return {'message': 'ok'}

    # 添加角色资源时,权限资源互斥
    def set_permission_mutual(self, role_id, resource_ids):
        print('参数》》》》', role_id, resource_ids, type(eval(resource_ids)))
        list5 = []
        for resource_id in eval(resource_ids):
            print('resource_id>>>', resource_id)
            # 通过资源id获取资源的二进制权限
            sql = "select * from resources where id=%d" % (int(resource_id))
            res = db1.get_one(sql)
            resource = res['resources_id']
            print('resource>>>>>', resource)
            list5.append(resource)
            if list5:
                print('list5>>>>>', list5)
                sql5 = "select * from resources_mutual"
                res5 = db1.get_all(sql5)
                print('res5>>>>>', res5)
                for i in res5:
                    re_id = i['resource_id']
                    mutual_id = i['mutual_id']
                    print('互斥id数据》》》》》', re_id, mutual_id, type(re_id))
                    # 如果互斥数据在要添加的资源id列表中,就说明有资源互斥问题
                    if re_id and mutual_id in list5:
                        return {'message': '资源互斥问题!', 'code': 507}
            # 根据角色id更新角色的二进制权限
            sql1 = "select * from role where id=%d" % (int(role_id))
            res1 = db1.get_one(sql1)
            role = res1['resources_id']
            print('role>>>>>', role)
            # 二进制位运算位或 |  添加
            res2 = resource | role
            print('res2>>>>', res2)
            sql3 = "update role set resources_id=%d where id=%d" % (int(res2), int(role_id))
            db1.update(sql3)
        return {'message': 'ok'}

    # 鉴权,判断此用户有没有某个单一权限
    def check_permission(self, role_id, resource_id):
        print('获取参数》》》》', role_id, resource_id)
        # 通过资源id获取资源的二进制权限
        sql = "select * from resources where resources_id=%d" % (int(resource_id))
        res = db1.get_one(sql)
        resource = res['resources_id']
        print('resource>>>>>', resource)
        sql2 = "select * from role where id=%d" % int(role_id)
        res2 = db1.get_one(sql2)
        print('res2>>>>>>>', res2)
        resource_ids = res2['resources_id']
        print('resource_ids>>>>>', resource_ids)
        result = resource_ids & resource
        print('result>>>>>', result)
        return result

    # 获取用户的权限列表  使用&来对比权限
    def get_permission(self, role_id):
        # 根据userid查询roleid  user和role表连接查询
        print('获取参数》》》', role_id)

        # 根据角色id查询角色的二进制权限
        sql = "select resources_id from role where id=%d" % int(role_id)
        res = db1.get_one(sql)
        role = res['resources_id']
        print('role>>>>>', role)
        # 查询所有资源
        sql2 = "select * from resources"
        res2 = db1.get_all(sql2)
        print('res2>>>>>', res2)
        list1 = []
        # 遍历资源,用角色的二进制权限 & 资源的二进制权限
        for i in res2:
            res_id = i['resources_id']
            if res_id != None:
                print('res_id>>>>>', res_id)
                result = role & res_id
                print('result>>>>>>', result)
                if result > 0:
                    list1.append(res_id)
        print('list1>>>>>', list1, len(list1))
        return list1

    # 删除某个权限   使用位运算符异或^来删除
    def del_permission(self, role_id, resource_id):
        print('获取参数》》》》', role_id, resource_id)
        # 根据角色id查询角色的二进制权限
        sql = "select resources_id from role where id=%d" % int(role_id)
        res = db1.get_one(sql)
        role = res['resources_id']
        print('role>>>>', role)
        # 通过资源id获取资源的二进制权限
        sql2 = "select resources_id from resources where resources_id=%d" % int(resource_id)
        res2 = db1.get_one(sql2)
        res_id = res2['resources_id']
        print('res2>>>>', res2)
        print('res_id>>>>', res_id)
        # 删除某个权限
        result = role ^ res_id
        print('result>>>>>', result)
        # 修改数据库
        sql3 = "update role set resources_id=%d where id=%d" % (int(result), int(role_id))
        db1.update(sql3)
        return {'message': 'ok'}

    # 删除角色对应的所有资源
    def del_all_permission(self, role_id):
        # 给角色添加资源,就要先将该角色的资源进行删除
        # 根据角色id更新角色的二进制权限为0
        sql = "update role set resources_id=%d where id=%d" % (0, int(role_id))
        db1.update(sql)
        return {'message': 'ok'}

    # 角色添加资源时选择继承基础角色并且进行资源互斥
    def role_add_permission_mutual(self, role_id, resource_ids, inherit_id):
        print('获取参数》》》》》》', role_id, resource_ids, inherit_id)
        sql = "select resources_id from role where id=%d" % (int(inherit_id))
        res = db1.get_one(sql)
        # 获取基础角色资源
        inherit = res['resources_id']
        list5 = []
        for resource_id in eval(resource_ids):
            print('resource_id>>>', resource_id)
            # 通过资源id获取资源的二进制权限
            sql6 = "select * from resources where id=%d" % (int(resource_id))
            res = db1.get_one(sql6)
            resource = res['resources_id']
            print('resource>>>>>', resource)
            list5.append(resource)
            if list5:
                print('list5>>>>>', list5)
                sql5 = "select * from resources_mutual"
                res5 = db1.get_all(sql5)
                print('res5>>>>>', res5)
                for i in res5:
                    re_id = i['resource_id']
                    mutual_id = i['mutual_id']
                    print('互斥id数据》》》》》', re_id, mutual_id, type(re_id))
                    # 如果互斥数据在要添加的资源id列表中,就说明有资源互斥问题
                    if re_id and mutual_id in list5:
                        return {'message': '资源互斥问题!', 'code': 507}
            # 根据角色id更新角色的二进制权限
            sql1 = "select * from role where id=%d" % (int(role_id))
            res1 = db1.get_one(sql1)
            role = res1['resources_id']
            print('role>>>>>', role)
            # 二进制位运算位或 |  添加
            # 1.先将基础角色资源和所选资源相加
            inherit_ids = resource | inherit
            print('inherit_ids>>>>>>', inherit_ids)
            # 2.在添加到角色资源中
            res2 = inherit_ids | role
            print('res2>>>>', res2)
            sql3 = "update role set resources_id=%d where id=%d" % (int(res2), int(role_id))
            db1.update(sql3)
        return {'message': 'ok'}

用户和角色多对多 

from common.models.cart_model import Resourse,Role

class BinPro:
    #授权
    def set_promition(self,userid,resourceid,role_id):
        """

        :param userid: 用户id
        :param resourceid: 资源id
        :param role_id: 要填权限的角色id
        :return:
        """
        # 先获取用户的所有角色
        role_all = [1, 3, 4]
        # 查询资源信息
        resourse = Resourse.query.get(resourceid)
        #判断要添加的权限的角色是否在角色列表中
        if role_id not in role_all:
            return {'msg':'用户所要填权限的角色不存在'}
        #查询角色信息
        role = Role.query.get(role_id)
        # 更新权限
        result = role.resource | resourse.resource
        role.resource = result
        db.session.add(role)
        db.session.commit()
        # role['binpromition'] | resource['binpromition']
        return 'ok'

    #鉴权,判断此用户有没有某个单一权限
    @classmethod
    def check_promition(cls,userid,resourceid):
        """
        :param userid: 用户id
        :param resourceid: 资源id
        :return:
        """
        # 方法一
        ##获取用户所有角色
        # role_id = [1, 3, 4]
        ##获取资源信息
        # resourse = Resourse.query.get(resourceid)
        # for i  in role_id:
        #     role = Role.query.get(i)
        ##判断是否拥有权限
        #     result = role.resource & resourse.resource
        #     if result != 0:
        #         return 'ok'
        # return 'no'
        #方法二:
        #获取用户所有角色
        role_id = [1, 3, 4]
        #获取所有用户角色信息
        permission = []
        for i in role_id:
            role = Role.query.get(i)
            permission.append(role)
        # 查询所有资源
        rosourse = Resourse.query.all()
        print(rosourse)
        # 遍历资源,用角色的二进制权限 & 资源的二进制权限
        list1 = []
        print(permission)
        for n in permission:
            if n:
                for i in rosourse:
                    result = n.resource & (i.resource)
                    #判断是否有该权限
                    if result > 0:
                        print(i.id)
                        _id = i.id
                        list1.append(i.id)
        # 权限去重
        list2 = list(set(list1))
        if resourceid in list1:
            return 'ok'
        return 'no'

    #获取用户的权限列表
    @staticmethod
    def get_promition(userid):
        #根据userid查询roleid  user和role表连接查询
        # , 角色和用户使用了多对多所有查询到多个角色
        # 根据角色id查询角色的二进制权限
        role_id = [1, 3, 4]
        permission = []
        for i in role_id:
            role = Role.query.get(i)
            permission.append(role)
        #查询所有资源
        rosourse = Resourse.query.all()
        print(rosourse)
        #遍历资源,用角色的二进制权限 & 资源的二进制权限
        list1 = []
        print(permission)
        for n in permission:
            if n:
                for i in rosourse:
                    result = n.resource & (i.resource)
                    if result > 0:
                        print(i.id)
                        _id = i.id
                        list1.append(i.id)
        #权限去重
        list2 = list(set(list1))
        print('>>>',list2)
        list3 = []
        for i in list2:
             list3.append(Resourse.query.get(i))
        return list3

    #删除某个权限
    @staticmethod
    def del_promition(roleid,resourceid):
        # 要删除的单个权限
        del_source = Resourse.query.get(resourceid)
        promition = del_source.resource
        permission = []
        #获取所有权限
        rosourse = Resourse.query.all()
        for i in roleid:
            role = Role.query.get(i)
            permission.append(role)
        # 删除单个权限
        for n in permission:
            if n:
                list1 = []
                for i in rosourse:
                    result = n.resource & (i.resource)
                    if result > 0:
                        list1.append(i.resource)
                if promition in list1:
                    result = n.resource ^ promition
                    n.resource = result
                    db.session.add(n)
                    db.session.commit()
        return 'ok'

    #删除角色对应的所有资源
     #删除某个权限
    @staticmethod
    def del_allpromition(roleid):
        for i in roleid:
            # 根据角色id更新角色的二进制权限为0
            role = Role.query.get(i)
            role.resource =0
            db.session.add(role)
            db.session.commit()
        return 'ok'


bin = BinPro()
调用测试代码

@test_bp.route('/testabc')
def binary_authority():
    # permission = BinPro.del_promition([1, 3, 4],3)
    # permission = BinPro.del_allpromition([1, 3, 4])
    # permission = BinPro.get_promition(3)
    # permission = BinPro.check_promition(1,2)
    permission = bin.set_promition(1, 3, 4)
    print(permission)
    return str(permission)

 注意

资源表中的resource是二的倍数

 角色后面的resource则是所拥有权限后面resource的和

例如角色 搜索 resource是3 那么他就有id为1,2两个权限

角色  踩踩踩 resource是8  那么他就有id为8这个权限

 二进制做奇偶数判断

alist = []
    blist = []
    for i in range(11):
        result = i & 1

等于0为偶数,非0为奇数
        if result == 0:
            alist.append(i)
        else:
            blist.append(i)
    print(alist)
    print(blist)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值