讲在前面的
我们一般在开发后台管理应用程序的时候,或多或少都会涉及到鉴权管理。鉴权管理中一般有角色、权限两部分组成,用户直接和角色关联,这种鉴权管理实现简单,在一些较小的项目中也比较容易实现,但是在一些比较大的项目中就有些局限性了,或者说对权限的要求更高、更细粒度。下面我主要讲下如果通过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,当然,你可以根据自己的需求代码里面去控制
权限、菜单、角色关系 -
我把4张表的一个ER图大概画了一下,标注了里面节点的一些含义
表之间的关联关系
下面解读下表结构
yauth_items表
= 权限条目表
-
item_code
=节点代码
// 用来做唯一标识 -
client_id
=客户端ID
// 用来标识是哪个客户端访问过来的用户,你总不想每做一个客户端都写一套rbac系统吧,比如有clientA
和clientB
,业务功能不同,权限也不同,通过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 递归查找依赖关系,可能会导致大量递归,使用左右值又丧失了依赖的优点,暂时没有想到好的解决办法
网友评论