本文章是自己在學習php的時候,使用thinkPHP開發一個簡單的OA系統,對RBAC權限管理的一個總結。
1. 權限管理(RBAC)
RBAC(role base access control ): 基於角色的用戶訪問權限控制
2.傳統方式的權限設置和基於角色權限控制的區別
1)傳統方式的權限設置
實現方式:具體的操作權限與用戶直接對應,如下所示:


該方式權限設置特點:
管理員需要為新增、離職的用戶進行具體權限分配,操作的時候
效率低下、
權限設置沒有統一標准,
較凌亂,不適合大項目使用。
2)基於角色的權限分配
該方式權限設置特點:
用戶----->組(角色)------>權限
用戶和組(角色)對應,組和權限對應
管理員進行權限設置只需要考慮用戶是哪個組的即可,操作非常容易、高效、簡便,
組別擁有的權限通過前期准備工作已經做好,權限設置非常標准化。
是一種非常科學的權限設置方式。
3. RBAC的原理

RBAC權限管理的表設計:

以下是oa系統權限管理的表設計
權限表--創建節點表---(體現能夠操作的控制器和方法)(加粗的一般是必須字段,node_module不一定必須,如果是在同一個模塊,就可以不用加module這個字段)
CREATE TABLE tp_node(
node_id INT(6) AUTO_INCREMENT PRIMARY KEY, #節點id
node_name VARCHAR(20) UNIQUE NOT NULL, #節點名稱
node_title VARCHAR(50) NOT NULL, #存放class name
node_pid SMALLINT(6) UNSIGNED NOT NULL, #父節點id
node_module VARCHAR(20) NOT NULL DEFAULT 'null', #模塊名
node_controller VARCHAR(20) NOT NULL DEFAULT 'null', #控制器
node_action VARCHAR(20) NOT NULL DEFAULT 'null', #方法
node_path VARCHAR(255) NOT NULL, #module-controller-action(例:admin-index-index)
node_level TINYINT(1) UNSIGNED NOT NULL, #用於區分菜單層級
node_sort TINYINT UNSIGNED NOT NULL, #用於排序
node_show TINYINT DEFAULT 1 #表明當前節點是否會顯示在左側的管理菜單中
)ENGINE=MYISAM DEFAULT CHARSET=utf8;
--節點添加
INSERT INTO tp_node VALUES (1,'日常辦公','office',0,'Admin','Main','home','Admin-Main-home',0,1,1);
--Dept控制器
INSERT INTO tp_node VALUES (2,'組織結構','agency',0,'','','','null',0,2,1);
INSERT INTO tp_node VALUES (3,'部門列表','',2,'Admin','Dept','index','Admin-Dept-index',1,21,1);
INSERT INTO tp_node VALUES (4,'添加部門','',2,'Admin','Dept','add','Admin-Dept-add',1,22,1);
INSERT INTO tp_node VALUES (5,'添加部門操作','',2,'Admin','Dept','addOk','Admin-Dept-addOk',1,23,0);
INSERT INTO tp_node VALUES (6,'刪除部門','',2,'Admin','Dept','del','Admin-Dept-del',1,24,0);
INSERT INTO tp_node VALUES (7,'編輯部門','',2,'Admin','Dept','edit','Admin-Dept-edit',1,25,0);
INSERT INTO tp_node VALUES (8,'修改部門','',2,'Admin','Dept','modify','Admin-Dept-modify',1,26,0);
INSERT INTO tp_node VALUES (9,'批量刪除','',2,'Admin','Dept','dels','Admin-Dept-dels',1,27,0);
--User控制器
INSERT INTO tp_node VALUES (10,'職員管理','nav-info',0,'','','','null',0,10,1);
INSERT INTO tp_node VALUES (11,'職員列表','',10,'Admin','User','index','Admin-User-index',1,101,1);
INSERT INTO tp_node VALUES (12,'添加職員','',10,'Admin','User','add','Admin-User-add',1,102,1);
INSERT INTO tp_node VALUES (13,'添加職員操作','',10,'Admin','User','addOk','Admin-User-addOk',1,103,0);
INSERT INTO tp_node VALUES (14,'ajax表格','',10,'Admin','User','getContent','Admin-User-getContent',1,104,0);
INSERT INTO tp_node VALUES (15,'統計圖','',10,'Admin','User','charts','Admin-User-charts',1,105,0);
INSERT INTO tp_node VALUES (16,'編輯職員','',10,'Admin','User','edit','Admin-User-edit',1,106,1);
INSERT INTO tp_node VALUES (17,'修改職員','',10,'Admin','User','modify','Admin-User-modify',1,107,0);
INSERT INTO tp_node VALUES (18,'刪除職員','',10,'Admin','User','del','Admin-User-del',1,108,0);
INSERT INTO tp_node VALUES (19,'公文起草','gongwen',0,'','','','null',0,19,1);
INSERT INTO tp_node VALUES (20,'公文管理','index',19,'Admin','Doc','index','Admin-Doc-index',1,191,1);
INSERT INTO tp_node VALUES (21,'添加公文','add',19,'Admin','Doc','add','Admin-Doc-add',1,192,1);
INSERT INTO tp_node VALUES (22,'知識管理','knowledge',0,'','','','null',0,22,1);
INSERT INTO tp_node VALUES (23,'知識列表','index',22,'Admin','Knowledge','index','Admin-Knowledge-index',1,221,1);
INSERT INTO tp_node VALUES (24,'添加知識','add',22,'Admin','Hnowledge','add','Admin-Knowledge-add',1,222,1);
INSERT INTO tp_node VALUES (25,'郵件管理','email',0,'','','','null',0,25,1);
INSERT INTO tp_node VALUES (26,'收件箱','index',25,'Admin','Email','index','Admin-Email-index',1,251,1);
INSERT INTO tp_node VALUES (27,'寫郵件','add',25,'Admin','Email','add','Admin-Email-add',1,252,1);
INSERT INTO tp_node VALUES (28,'系統管理','system',0,'','','','null',0,7,1);
INSERT INTO tp_node VALUES (29,'角色管理','role',28,'Admin','Role','index','Admin-Role-index',1,281,1);
INSERT INTO tp_node VALUES (30,'節點管理','node',28,'Admin','Node','index','Admin-Node-index',1,282,1);
--創建角色表--
CREATE TABLE tp_role( #加粗的是必須的字段
role_id INT AUTO_INCREMENT PRIMARY KEY, #角色id
role_name VARCHAR(20) UNIQUE NOT NULL, #角色名
role_ids VARCHAR(255) NOT NULL, #權限id列表
role_path VARCHAR(255) NOT NULL #module-controller-action(例:admin-index-index)
)ENGINE=MYISAM DEFAULT CHARSET=utf8;
//user表(加粗的是必須字段,其他字段根據具體需求添加)
create table tp_user(
id int not null auto_increment primary key,
username varchar(40) not null,
roleid int not null default 0, #角色id
password char(32) not null,
nickname varchar(40),
deptid int not null,
sex varchar(10) not null,
birthday date not null,
tel varchar(11) not null,
email varchar(50) not null,
addtime int
) engine=myisam default charset=utf8;
RBAC權限訪問最終體現在兩個地方:
1)動態生成左側管理菜單
2)防跳牆訪問
動態生成左側管理菜單
思路:
①
在用戶登錄時,在session中記錄該用戶的user_roleid字段。
②
根據roleid的值從role表取出改用戶可以操作的所有權限的節點id(role_ids)
③
根據ids從node表中取出具體可以操作的權限
防跳牆訪問
在TP當中定義了3個常量:MODULE_NAME(當前訪問的模塊名)、CONTROLLER_NAME(當前訪問的控制器名)、ACTION_NAME(當前訪問的方法名)
MODULE_NAME-CONTROLLER_NAME-ACTION_NAME
CommonController控制器,
_initialize
() 在實例化控制器時,自動調用(_initialize()是tp的controller類中,構造方法
有一段代碼if(method_exists($this,'_initialize'))
$this->_initialize();
_initialize()方法在controller中,並沒有定義,就是給后面繼承該控制器的類使用的。這里的CommonController控制器就是通過這個原理實現的
)
-
在CommonController/_initialize()方法中,用模塊名、控制器名、方法名組成一個字符串。
-
使用上步產生的字符串和role表當中的role_path進行比較,如果字符串存在於role_path字段中,則說明正常訪問;反之,則為跳牆訪問。
①
根據session中的roleid,從role表中獲取role_path字段。 在登錄時,就把role_path記錄在session中。
②
在CommonController/_initialize()方法中,使用獲取到的當前模塊控制器方法的字符串和session中的rolepath進行比較。