文章-如何設(shè)計(jì)數(shù)據(jù)庫(kù)表實(shí)現(xiàn)完整的RBAC(基于角色權(quán)限控制)
【RBAC】打造Web權(quán)限控制系統(tǒng)
這種關(guān)系的講解失受,推薦一篇文章--[文章2]
- 先看幾張圖引润,了解下
RBAC
ACL是用戶直接擁有權(quán)限,RBAC是用戶通過(guò)角色來(lái)?yè)碛械臋?quán)限。與權(quán)限之間是間接關(guān)系
- RBAC簡(jiǎn)化了用戶和權(quán)限的關(guān)系禁荒,易擴(kuò)展和維護(hù)
數(shù)據(jù)庫(kù)設(shè)計(jì)-- 要時(shí)刻牢記一個(gè)原則,用戶是通過(guò)角色來(lái)?yè)碛械臋?quán)限寺庄。也就是用戶是跟角色有關(guān)聯(lián)耀石,而跟權(quán)限沒(méi)有關(guān)聯(lián)
開(kāi)發(fā)之前有必要先來(lái)分析一下數(shù)據(jù)表:
我們給角色賦權(quán)限,讓角色與用戶關(guān)聯(lián)
- 1.用戶表--users
- 2.權(quán)限表--permissions
- 3.角色表--roles
- 4.角色表和權(quán)限表--role_permission
- 5.用戶和角色表--user_role
drop table `permissions` if EXISTS ;
CREATE TABLE IF NOT EXISTS `permissions` (
`id` int(11) NOT NULL auto_increment,
`Title` char(64) NOT NULL,
`Description` text NOT NULL,
`slug` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`http_path` text COLLATE utf8mb4_unicode_ci,
PRIMARY KEY (`id`),
KEY `Title` (`Title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='權(quán)限表';
slug表示權(quán)限的名稱硬爆,比如登錄
http_path表示uri路徑 比如 /login /logout
drop table `roles` if EXISTS ;
CREATE TABLE IF NOT EXISTS `roles` (
`id` int(11) NOT NULL auto_increment,
`Title` varchar(128) NOT NULL,
`Description` text NOT NULL,
PRIMARY KEY (`id`),
KEY `Title` (`Title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='角色表';
drop table `role_permission` if EXISTS ;
CREATE TABLE IF NOT EXISTS `role_permission` (
`role_id` int(11) NOT NULL,
`premission_id` int(11) NOT NULL,
PRIMARY KEY (`role_id`,`premission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='角色權(quán)限表';
drop table `user_role` if EXISTS ;
CREATE TABLE IF NOT EXISTS `user_role` (
`user_id` int(11) NOT NULL,
`role_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='用戶角色表';
當(dāng)然欣舵,還有user表。此處不再寫(xiě)
`role_permission` 表里可以使用 PRIMARY KEY (`role_id`,`premission_id`)索引缀磕。無(wú)需自增id 缘圈。`user_role`表也是一樣
在使用上:
`user_role` 的表,哪個(gè)用戶想擁有哪個(gè)菜單的角色袜蚕,就在這個(gè)表添加一條數(shù)據(jù)
`role_permission` 的表糟把,哪個(gè)角色想擁有哪個(gè)權(quán)限,就在這個(gè)表添加一條數(shù)據(jù)
這樣我們只是建好了表牲剃,但實(shí)際我們是要用于某些后臺(tái)連接點(diǎn)擊權(quán)限的
所以我們還需要兩張表鏈接菜單表menus
和用戶和鏈接菜單表role_menu
drop table `role_menu` if EXISTS ;
CREATE TABLE `role_menu` (
`role_id` int(11) NOT NULL,
`menu_id` int(11) NOT NULL,
PRIMARY KEY (`role_id`,`menu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='用戶和鏈接菜單表';
drop table `menus` if EXISTS ;
CREATE TABLE `menus` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`order` int(11) NOT NULL DEFAULT '0' COMMENT '排序遣疯,這個(gè)表可以不要',
`title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`uri` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='鏈接菜單表';
`role_menu` 的表,哪個(gè)角色想擁有哪個(gè)菜單的權(quán)限凿傅,就在這個(gè)表添加一條數(shù)據(jù)
- 此處推薦一篇文章php 遞歸無(wú)限分類
再進(jìn)一步想缠犀,我們可以通過(guò)管理組來(lái)與用戶關(guān)聯(lián).此處的組数苫,可以理解為上面的角色。那么我們需要如下兩個(gè)表辨液。我們給組賦權(quán)限虐急,讓組與用戶關(guān)聯(lián)
drop table `groups` if EXISTS ;
CREATE TABLE IF NOT EXISTS `groups` (
`id` int(11) NOT NULL auto_increment,
`Title` varchar(128) NOT NULL,
`Description` text NOT NULL,
PRIMARY KEY (`id`),
KEY `Title` (`Title`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='用戶組表';
drop table `group_permission` if EXISTS ;
CREATE TABLE IF NOT EXISTS `group_permission` (
`premission_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
`slug` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`http_path` text COLLATE utf8mb4_unicode_ci,
PRIMARY KEY (`group_id`,`premission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='角色組';
drop table `user_group` if EXISTS ;
CREATE TABLE IF NOT EXISTS `user_group` (
`group_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='角色組與用戶表';
第二部分,使用篇
上面我們介紹完表關(guān)聯(lián)設(shè)計(jì)后滔迈,接下來(lái)談一談怎么使用止吁。使用的時(shí)候應(yīng)該是某個(gè)角色
role
可以操作某些路由,所以應(yīng)該有兩個(gè)表亡鼠。路由表menu
和角色路由表role_menu
CREATE TABLE `role_menu` (
`role_id` int(11) NOT NULL,
`menu_id` int(11) NOT NULL,
KEY `role_menu_role_id_menu_id_index` (`role_id`,`menu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `menu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`order` int(11) NOT NULL DEFAULT '0',
`title` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`uri` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
此處我講下路由限制的menu
表赏殃,
parent_id
就是本url屬于哪個(gè)層級(jí)(這里用的是無(wú)限分類)
比如此處表單和test都在4Roles
下面
order
是列表顯示的排序敷待,序號(hào)小的在上面间涵,此處表單在test上面
uri
是角色可以訪問(wèn)的路由,自己通過(guò)代碼限制即可
menu與
role_menu`表的配合是指圖中最坐變那排圖標(biāo)的顯示
然后是 permissions
中 slug
榜揖、http_path
字段也是路由限制勾哩,permissions
是表示直接在瀏覽器上輸入路由不可以訪問(wèn)
要說(shuō)明的是,如果不顯示圖標(biāo)的情況举哟,如果你沒(méi)做路由訪問(wèn)限制思劳,輸入對(duì)應(yīng)的uri其實(shí)也是可以訪問(wèn)頁(yè)面的。
我們?cè)陲@示某個(gè)用戶的菜單列表的時(shí)候妨猩,
在role_menu
表中潜叛,role_id
,menu_id
都可以是多個(gè)
1.通過(guò)user.id
查到role_menu.menu_id集合
,
2.然后查到符合menu_id
集合的menu.id
顯示出來(lái)
在做某個(gè)用戶訪問(wèn)某個(gè)路由的時(shí)候
role_user
表中user_id
是唯一的,role_id
是可以多個(gè)的
1.通過(guò)user.id
得到role_user.role_id
2.然后得到role_permissions
表中的permissions
.(表中的permissions_id和role_id都可以是多個(gè))
3.去permissions
表取出id
對(duì)應(yīng)的uri
(即http_path
)數(shù)據(jù)