3+1 张表建立一个强大的RBAC鉴权管理系统

讲在前面的

我们一般在开发后台管理应用程序的时候,或多或少都会涉及到鉴权管理。鉴权管理中一般有角色、权限两部分组成,用户直接和角色关联,这种鉴权管理实现简单,在一些较小的项目中也比较容易实现,但是在一些比较大的项目中就有些局限性了,或者说对权限的要求更高、更细粒度。下面我主要讲下如果通过3+1来实现鉴权管理。


3 指的是3张鉴权表设计

  • yauth_items,这张表记录的是鉴权节点表,表结构如下:
CREATE TABLE `yauth_items` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `item_code` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `client_id` INT(10) UNSIGNED NULL DEFAULT NULL,
    `user_id` INT(10) UNSIGNED NULL DEFAULT NULL,
    `item_name` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `item_desc` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `item_type` TINYINT(3) UNSIGNED NOT NULL,
    `scope` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `other_data` TEXT NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `yauth_items_item_code_unique` (`item_code`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB;
  • yauth_item_relation,这张表记录的是鉴权节点之间的层级关系
CREATE TABLE `yauth_item_relation` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `item_id` INT(10) UNSIGNED NOT NULL,
    `client_id` INT(10) UNSIGNED NOT NULL,
    `scope` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `parent_id` INT(11) NULL DEFAULT NULL,
    `lft` INT(11) NULL DEFAULT NULL,
    `rgt` INT(11) NULL DEFAULT NULL,
    `depth` INT(11) NULL DEFAULT NULL,
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `yauth_menus_item_id_index` (`item_id`),
    INDEX `yauth_menus_parent_id_index` (`parent_id`),
    INDEX `yauth_menus_lft_index` (`lft`),
    INDEX `yauth_menus_rgt_index` (`rgt`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB;
  • yauth_item_group,这张表是记录鉴权节点之间的依赖关系
CREATE TABLE `yauth_item_group` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `parent_id` INT(10) UNSIGNED NOT NULL,
    `child_id` INT(10) UNSIGNED NOT NULL,
    `client_id` INT(10) UNSIGNED NOT NULL,
    `scope` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `yauth_item_relation_parent_id_index` (`parent_id`),
    INDEX `yauth_item_relation_child_id_index` (`child_id`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB;

1 指的是用户分配(关联)表设计

  • yauth_assignments,这张表指的是用户和鉴权节点如何进行分配(关联)
CREATE TABLE `yauth_assignments` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `item_id` INT(10) UNSIGNED NOT NULL,
    `user_id` INT(10) UNSIGNED NOT NULL,
    `provider` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `deleted_at` TIMESTAMP NULL DEFAULT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `yauth_assignments_user_id_index` (`user_id`),
    INDEX `yauth_assignments_item_id_index` (`item_id`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB;

简单说下鉴权管理的思路

  • 一切皆节点,节点包括权限、菜单、角色等等
  • 节点之间没有显示的层级关系,比如菜单包含权限,角色包含权限,但是权限不能包含菜单,这个需要根据需求在代码里面实现
  • 权限、菜单、角色三者之间的关系如下,并且同级之间也可以相互包含,比如角色A包含角色B,当然,你可以根据自己的需求代码里面去控制


    7893223-fab8b74482e5212b.png
    权限、菜单、角色关系
  • 我把4张表的一个ER图大概画了一下,标注了里面节点的一些含义


    7893223-f4103c29080764f1.png
    表之间的关联关系

下面解读下表结构

yauth_items表 = 权限条目表

  • item_code = 节点代码 // 用来做唯一标识
  • client_id = 客户端ID // 用来标识是哪个客户端访问过来的用户,你总不想每做一个客户端都写一套rbac系统吧,比如有clientAclientB,业务功能不同,权限也不同,通过client_id我们就能根据client找到该机构下拥有的权限,来判断权限该用户是否有权限
  • user_id = 用户ID
  • item_name = 节点名称 // 比如该节点是一个菜单、它的名字叫 首页
  • item_desc = 节点描述 // 给节点添加更详细的描述信息
  • item_type = 节点类型 // 节点的类型 权限、菜单、角色,可以根据需要扩充
  • scope = 作用域 // 将这些节点进行作用域划分,比如同样是菜单,分为顶部菜单和左侧菜单,多个作用域用逗号隔开,比如超管的菜单和机构的菜单
  • other_data = 其他数据// 扩展字段,我们可以为某些节点添加一些别的标识以便做特殊处理

yauth_item_relation表 = 节点关系表

  • item_id = 节点id // 对应yauth_items表id
  • client_id = 客户端ID // 同上,标识归属于哪个客户端
  • scope = 作用域 // 该节点属于哪个作用域,单一作用域
  • parent_id = 父id // 关联本表的id字段
  • lft = 左值 // 详情可见左右值算法
  • right = 右值 // 详情可见左右值算法
  • depth = 层级 // 代表该节点的层级深度

yauth_item_group表 = 节点分组表

  • parent_id = 父ID // 关联yauth_items表的id字段
  • child_id = 子ID // 关联yauth_items表的id字段
  • client_id = 客户端ID // 区分客户端
  • scope = 作用域 // 建立依赖时,在哪个作用域范围添加的

yauth_assignments = 权限分配表

  • item_id = 节点ID // yauth_items表id
  • user_id = 用户ID //
  • provider = 用户提供这 // 用来标识是哪个表提供的用户,适用于多表用户

总结:

  • yauth_items 用来存储节点,我们添加的所有节点都在这样表中
  • yauth_item_relation 用来表示节点的层级关系,不然我们看到视图不够直观。注意,添加到yauth_items表是第一步,我们将节点挂载到yauth_item_relation表,才应该生效
  • yauth_item_group 用来标识节点之间的依赖关系,角色A依赖角色B,角色B依赖菜单A、菜单B,菜单A依赖权限A,给用户分配了角色A相当于拥有了角色B、带单A、菜单B、权限A
  • 这套设计操作起来可能会比较麻烦,比如添加权限这个操作,需要先添加、在挂载、在添加依赖,不过权限这个东西本来不就随着业务要求越高越复杂么
  • 在依赖判断时,yauth_item_group表parent_id 和 child_id 递归查找依赖关系,可能会导致大量递归,使用左右值又丧失了依赖的优点,暂时没有想到好的解决办法

猜你喜欢

转载自blog.csdn.net/weixin_34327761/article/details/87036204