PHPCMS中的RBAC權限系統主要用到了4張數據表:管理員表,角色表,菜單表,菜單權限表。先來看看數據庫的數據表結構:
admin 管理員表
ID | 字段 | 類型 | Null | 默認 | 索引 | 額外 | 注釋 |
---|---|---|---|---|---|---|---|
1 | userid | mediumint(6) | unsigned | PK | auto_increment | 用戶id | |
2 | username | varchar(20) | YES | INDEX | 用戶名 | ||
3 | password | varchar(32) | YES | 密碼 | |||
4 | roleid | smallint(5) | YES | 0 | 角色 | ||
5 | encrypt | varchar(6) | YES | 加密因子 | |||
6 | lastloginip | varchar(15) | YES | 最后登錄ip | |||
7 | lastlogintime | int(10) unsigned | YES | 0 | 最后登錄時間 | ||
8 | varchar(40) | YES | |||||
9 | realname | varchar(50) | NO | 真實姓名 | |||
10 | card | varchar(255) | NO | 密保卡 |
admin_role 角色表
ID | 字段 | 類型 | Null | 默認 | 索引 | 額外 | 注釋 |
---|---|---|---|---|---|---|---|
1 | roleid | tinyint(3) unsigned | PK | auto_increment | 角色id | ||
2 | rolename | varchar(50) | NO | 角色名稱 | |||
3 | description | text | NO | 描述 | |||
4 | listorder | smallint(5) unsigned | NO | 0 | INDEX | 排序 | |
5 | disabled | tinyint(1) unsigned | NO | 0 | INDEX | 狀態:1,禁用 |
menu 菜單表
ID | 字段 | 類型 | Null | 默認 | 索引 | 額外 | 注釋 |
---|---|---|---|---|---|---|---|
1 | id | smallint(6) unsigned | PK | auto_increment | 菜單id | ||
2 | name | char(40) | NO | 名稱 | |||
3 | parentid | smallint(6) | NO | 0 | INDEX | 父id | |
4 | m | char(20) | NO | INDEX | m | ||
5 | c | char(20) | NO | INDEX | c | ||
6 | a | char(20) | NO | INDEX | a | ||
7 | data | char(100) | NO | 附件參數 | |||
8 | listorder | smallint(6) unsigned | NO | 0 | INDEX | 排序 | |
9 | display | enum('1','0') | NO | 1 | 是否顯示,1 顯示 |
admin_role_priv 菜單權限表
ID | 字段 | 類型 | Null | 默認 | 索引 | 額外 | 注釋 |
---|---|---|---|---|---|---|---|
1 | roleid | tinyint(3) unsigned | 0 | PK | 角色id | ||
2 | m | char(20) | NO | INDEX | m | ||
3 | c | char(20) | NO | INDEX | c | ||
4 | a | char(20) | NO | INDEX | a | ||
5 | data | char(30) | NO | 附件屬性 | |||
6 | siteid | smallint(5) unsigned | NO | 0 | INDEX | 所屬站點 |
下面來簡單分析一下4張表的關系:
1.用戶表中的每個用戶有一個角色字段roleid,表明了該用戶屬於哪個角色。
2.角色表的主鍵為roleid,與用戶表中的roleid相對應,還有角色名稱,描述等,比如PHPCMS系統默認有超級管理員、總編、發布人員等角色。
3.管理員權限表中主鍵也是roleid,與角色表中的主鍵roleid相對應,表明了該角色擁有的后台操作權限。字段m、c、a分別代表的是模型 | 控制器 | 方法,因為PHPCMS本身也是MVC結構,所以更好地使權限系統的粒度細化到方法上面。
4.菜單表主要存放菜單屬性,其中的m、c、a與管理員權限表中的字段相對應。
最后來看看用戶的操作及驗證流程:
首先,用戶在后台登錄,如果登錄成功,將roleid(角色id)存入SESSION,然后跳轉到后台首頁,在PHPCMS系統中,整個后台操作的部分都在admin模塊中,所以該模塊中所有的控制器均繼承自admin類,並且在構造方法中執行了父類的構造方法(admin的構造方法)。那么,admin類的構造方法有執行了哪些操作呢?
首先是調用自身的 check_admin()
來判斷用戶是否登錄,緊接着判斷用戶的權限: check_priv()
check_priv() 方法源代碼:
## 格式略微修改
final public function check_priv()
{
if (ROUTE_M == 'admin' && ROUTE_C == 'index' && in_array(ROUTE_A, array('login', 'init', 'public_card'))) {
return true;
}
if ($_SESSION['roleid'] == 1) {
return true;
}
$siteid = param::get_cookie('siteid');
$action = ROUTE_A;
$privdb = pc_base::load_model('admin_role_priv_model');
if (preg_match('/^public_/', ROUTE_A)) {
return true;
}
if (preg_match('/^ajax_([a-z]+)_/', ROUTE_A, $_match)) {
$action = $_match[1];
}
$r = $privdb->get_one(
array(
'm' => ROUTE_M,
'c' => ROUTE_C,
'a' => $action,
'roleid' => $_SESSION['roleid'],
'siteid' => $siteid
)
);
if (!$r) {
showmessage('您沒有權限操作該項', 'blank');
}
}
該方法首先判斷當前正在進行的操作,如果是登錄或者初始化操作,則退出。
然后判斷角色是否為超級管理員(超級管理員默認為最高權限),如果是,依舊退出,或者如果當前方法為公開的(沒有權限限制),同樣退出。
最后加載 admin_role_priv_model,也就是管理員權限模型,獲取當前要操作的模型 | 控制器 | 方法,利用 admin_role_priv_model 提供的方法進行查詢,如果可以返回數據,則說明角色可以進行當前操作,反之,彈出提示信息:您沒有權限操作該項,然后退出!
對了,忘了介紹后台菜單的生成過程啦!其實用到的還是admin類自身的方法:admin_menu(): 不過該方法是在 index.tpl.php 模板中調用的,主要進行的操作是先取出菜單表中所有菜單,然后判斷當前角色,如果為超級管理員,則直接返回菜單數組,反之,則將符合當前角色權限的菜單數組返回。
以上就是PHPCMS系統的權限結構及操作流程!