国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

基于ThinkPHP的RBAC權限管理的設計與實現(xiàn)

2018-01-14 12:35謝飛翔黃謙
活力 2018年18期

謝飛翔 黃謙

【摘要】權限認證作為信息管理系統(tǒng)中必要的重要組成部分,它不僅要提供安全、可靠、高效的權限認證,而且應具備很好的適應性和靈活性以滿足不同信息系統(tǒng)的需求。本文正是基于以上理念,給出了一個通用RBAC數(shù)據(jù)庫設計方案,并以ThinkPHP框架為開發(fā)環(huán)境,著重介紹了系統(tǒng)權限的設置、分配和驗證。

【關鍵詞】權限控制:權限驗證;RBAC;ThinkPHP

引言

權限認證模塊在任何一個信息管理系統(tǒng)中都是不可或缺的,能有效防止非法用戶訪問系統(tǒng)資源以及合法用戶越權使用系統(tǒng)資源。

目前主要的訪問控制技術有自主訪問控制、強制訪問控制和基于角色的訪問控制等,從優(yōu)越性上看,RBAC優(yōu)于前兩者,RBAC是基于角色的訪問控制,通過角色可以很好地把權限和用戶獨立開來,因此RBAC是目前信息系統(tǒng)的主流設計模型,尤其被廣泛應用于Web信息管理系統(tǒng)。

本文以RBAC模型為核心理念,基于TinkPHP優(yōu)越的框架底層,實現(xiàn)了Web環(huán)境下,以角色為基礎的權限控制功能。

一、RBAC模型簡介

簡單而言,RBAC核心思想是提出了角色(Role)的概念,把用戶與權限相分離。主要包括三個要素,用戶、角色和權限。權限與角色相關聯(lián),用戶通過成為適當角色的成員而得到這些角色對應的權限。這就極大地簡化了權限的管理。角色可依據(jù)新的需求被賦予新的權限,而權限也可根據(jù)需要而從某角色中回收。一個用戶可以根據(jù)需要被指派多個角色以適應更為靈活的系統(tǒng)需求。

本文所采用的RBAC模型包括用戶(USERS)、角色( ROIES)和權限(PRMS)等3類實體集合。三者之間的邏輯關系如圖1所示。

每個角色至少具備一個權限,每個用戶至少扮演一個角色;可以對兩個完全不同的角色分配完全相同的訪問權限;需要強調的是,將用戶和許可權進行分離,使得彼此相互獨立,它們之間是多對多的關系,這種關系將使得模型具備足夠的靈活性以適應不同的系統(tǒng)需求。如,企業(yè)副總經(jīng)理兼任財務總監(jiān),該用戶將一身兼兩職,也將同時擁有兩個角色的權限。

二、RBAC數(shù)據(jù)庫設計

RBAC就是用戶通過角色與權限進行關聯(lián),一個用戶擁有若干角色,每一個角色擁有若干權限。這樣,就構造成“用戶一角色一權限”的授權模型。在這種模型中,用戶與角色之間,角色與權限之間,一般是多對多的關系?;谝陨蟁BAC思想,給出圖2所示的數(shù)據(jù)庫設計概要,鑒于突出問題重點,省去了表中的一些通用業(yè)務字段。

用戶表與角色表之間的關系是多對多的關系,中間表為用戶角色分配表,一個用戶可以指定多個角色,一個角色也可以同時分配給多個用戶;角色表與權限表之間的關系也是多對多的關系,中間表為角色權限分配表,一個角色可以指定擁有多個權限,一個權限也可以同時分配給多個角色。

三、RBAC系統(tǒng)功能的實現(xiàn)

ThinkPHP是一個免費開源的,快速、簡單的面向對象的輕量級PHP開發(fā)框架,是為了敏捷WEB應用開發(fā)和簡化企業(yè)應用開發(fā)而誕生的。本文擬基于ThinkPHP實現(xiàn)RBAC的權限管理、用戶管理、角色管理、用戶授權及認證等功能。

(一)RBAC權限的設置和分配

在數(shù)據(jù)庫設計中,我們知道程序中核心的數(shù)據(jù)庫表有用戶表( user)、角色表(role)、用戶角色分配表(role_user)、權限表(node)、角色權限分配表(access)等5張表。以下重點討論,程序怎樣實現(xiàn)系統(tǒng)權限的設置和分配的。

1. RBAC權限的設置

權限的設置是基于系統(tǒng)權限表(node),表結構及樣例如圖3所示。

可見,所有權限節(jié)點都有一個pid值,意為其父親節(jié)點id,如果pid-0,表示當前節(jié)點為模塊級權限,同時對應level-1,意為一級根節(jié)點,所有當前模塊下授權控制器和方法都會隸屬于該根節(jié)點;每一個授權控制器對應一個pid-l/level-2/type-1的二級節(jié)點,意為隸屬xfadmin模塊的二級控制器節(jié)點;每一個授權控制器方法對應一個pid-n/level-3/type-0的三級節(jié)點,意為隸屬n號控制器的三級方法節(jié)點,如,29號節(jié)點是隸屬于“用戶管理”控制器的“添加”方法節(jié)點。通過pid、level、type三個字段的合理設置,所有權限節(jié)點就構成了一棵權限樹。說明:表中 group_id并非rbac的要素字段,該字段設置的目的是對所有節(jié)點功能進行分組,便于在前臺界面進行展示,group_id=0,表示未分組,該權限只作為功能點存在,并不會在功能界面展示;groupid>0,表示進行了分組,該權限會以獨立的功能點展示在前臺界面中。

name和title是權限的名稱和標題,name屬性對應具體程序的模塊名、控制器名。如,34號結點是xfadmin模塊下的AdminUser控制器下的password方法。title字段主要是前臺展示時的標記名。

系統(tǒng)權限管理功能主要有:權限添加、權限刪除、權限編輯、權限禁用與恢復等幾個核心操作;權限節(jié)點分為一級模塊節(jié)點,如“后臺管理”,二級控制器節(jié)點,如“節(jié)點管理”,三級方法節(jié)點,如“添加”。

下面重點看看“添加”權限功能,其實現(xiàn)代碼是AdminNode\add方法,下面重點看看“添加”權限功能,其實現(xiàn)代碼是AdminNo de\add方法,對應源碼片段為:

public function add() {

$controller - $this->request->controller();

if ($this->request->isAjax() {

$data - $this->request->except(['id']);

if (

class exists($validateClass = Loader: :parseClass(Config: :get(app.validate_path'), 'validate'. $controller))) {

$validate - new $validateClass();

if (!$validate->check($data)) {return ajax_return_adv_error($validate->getError));}

}

if (

classexists($mo deIClass - Loader: :parseClass(Config : :get(' app.mo del_path'), 'model'. $this->parseCameICase($controller)))

||classexists($modeIClass=Loader::parseClass(Config::get(app.model_path'), 'model', $controller))) {

$model=new $modeIClass();

$ret=$model->isUpdate(false)->save($data);

} else {

Db : :startTrans();

try {

$model=Db::name($this->parseTable($controller));

$ret=$model->insert($data);

Db: :commit();

} catch(\Exception $e) {

Db::rollback();

return ajax_return_adv_error($e->getMessage());

}

}

return ajax_return_adv('success');

} else {

return $this->view->fetch(isset($this->template) ?$this->template:'edit');

}

}

代碼分析:由以上代碼分析可知,該add方法實際上一個通用添加方法,控制器名稱對應數(shù)據(jù)庫表名和驗證器名稱,用戶在訪問控制器時,程序會自動調用對應的驗證器和數(shù)據(jù)庫表進行數(shù)據(jù)處理。另外,可以針對不同的控制器在模型庫中定義不同的模型,充分體現(xiàn)了程序設計擴展性的優(yōu)越性。

2. RBAC權限的分配

權限設置完之后,就需要基于用戶表(user)、用戶角色表(roleuser)、角色表(role)、角色權限表(access)將權限分配給用戶。其邏輯是先基于“角色權限表”將權限分配給角色,然后再基于“用戶角色表”將角色分配給用戶,進而完成用戶權限的授權。

(1)角色授權

角色表包括的核心字段有id和name,角色權限表包括核心字段有role id、node id,其中 role id對應角色表id,node id對應node表id;一個角色分配了一個權限就會生成一條角色權限表記錄,一個角色可以分配若干個權限,同一個權限可以被分配給多個角色。

角色的授權功能在角色管理模塊中實現(xiàn),通過過添加功能創(chuàng)建角色后,可以立即通過授權功能對其進行權限分配,系統(tǒng)權限會以樹型的方式提供給用戶進行選擇分配,操作界面如圖4所示。

以上所有功能都是通過AdminRole控制器來實現(xiàn)的,其中角色授權是通過AdminRole\access方法實現(xiàn)的,access方法源碼為:

public function access(){

$roleid=$this->request->param('id/d');

if ($this->request->isPost()){

if(! $role_id){return ajax_return adv error(''缺少

必要參數(shù)'');}

if (

true !==$error=Loader::modeI('AdminAccess', 'Iogic')->insertAccess($role_id, $this->request->post()》

{return ajax_return_adv_error($error); }

retum ajax_return_adv("權限分配成功", ");

} else {

if (!$roleid) {throw new Exception("缺少必要參

$tree=Loader::model('AdminRole','Iogic')->getAccessTree($role_id);

$this->view->assign("tree", json_encode($tree));

return $this->view->fetch();

}

}

代碼分析:用戶執(zhí)行授權時,程序首先會執(zhí)行else部分,程序獲取請求的參數(shù)是角色id,然后再通過logic\AdminRole功能類的get Access Tree方法拿到當前角色的權限集,該權限是根據(jù)用戶id(UID)查詢出的當前用戶所擁有的權限集,也即用戶只能基于自己擁有的權限進行再分配,這個功能是很多企業(yè)所需要的。

當用戶分配完權限后通過保存功能,執(zhí)行角色權限的保存,其實就是執(zhí)行access方法的$this->request->isPost()條件為真的部分,代碼中通過logic\Admin Access功能類的rnsertAccess方法完成角色權限的保存,insertAccess參數(shù)錯誤

public function insertAccess($role_id, $data){

Db::startTrans();

try{

$db access=Db::name("AdminAccess");

$db access->where("role_id". $role_id)->delete0;

if (isset($data['node_id'])&&!empty($data['node_id'])&&isarray($data['nodeid'])){

$insert_all=[];

foreach($data['nodeid']as$v){

$node=explode(‘_,$v);

if(!isset($node[2])){throw new Exception('參數(shù)錯誤);}

$insert_all[]=[

“roleid”=> $role_id.

。"node_id"=> $node[0],

“l(fā)evel"=> $node[1],

"pid"=_> $node[2],

];

}

$db access->insertAll($insert_all);

}

Db::commit();

return true:

} catch (\Exception $e){

Db::rollback();

return $e->getMessage();

}

}

代碼分析:代碼使用的Think PHP的數(shù)據(jù)庫事務處理,方法參數(shù)為角色id($role id)和待插入權限數(shù)據(jù)($data),訪問rbac配置文件的access table值讀取到access表名,先刪除當前角色的所有現(xiàn)有權限,然后通過foreach遍歷$data的node id數(shù)據(jù),把數(shù)據(jù)再組裝成access表結構數(shù)據(jù)$insert all,最后通過Db::insertAII把數(shù)據(jù)一次。降插入到access數(shù)據(jù)表中,完成角色權限的保存。在代碼中利用了事務機制很好的保障了角色權限數(shù)據(jù)的完整性和有效性。

(2)用戶授權

用戶表的核心字段有id、account、realname、password等,用戶角色表包括字段有role_id,user_id,其中 role_id對應role表的id,user_id對應user表的id,一個用戶分配了一個角色就會生成一條用戶角色表記錄,一個用戶可以同時擁有多個角色,同一個角色可以被分配給多個用戶。

分配角色的邏輯過程為:首先基于user表創(chuàng)建一條用戶記錄,然后基于role_user表為該用戶創(chuàng)建一條或多條角色分配記錄。程序中實現(xiàn)該過程是通過用戶管理和角色管理來實現(xiàn)的。

在“角色管理”中選中待分配的角色項,點擊對應的“用戶列表”功能按鈕,程序會彈出當前系統(tǒng)用戶列表,然后再勾選需要分配的用戶,保存即可。該過程使用到的代碼是AdminRole\user方法,源碼片段為:

public function user(){

$roleid=$this->request->param(‘id/d);

if ($this->request->isPost()){

if(! $role_id){return ajax_return_adv_error(“缺少必要參數(shù)”);}

$db role user=Db::name(“AdminRoleUser”);

$db role user->where(“role id”,$roleid)->delete();

$data=$this->request->post();

if (isset($data[‘user_id])&&!empty($data[‘user_id])&&is_array($data[‘user_ id])){

$insert_all=[]

foreach ($data[‘user_ id]as$v){

$insert_all[]=[

“role_id”=>$role_id.

“user_ id”=>intval($v),

];

}

$db_role_user->insertAll($insert_all);

}

return ajax_return_adv(“分配角色成功”,”);

) else{

if (!$roleid){

throw new Exception(“缺少必要參數(shù)”);

$list user=Db::name(“AdminUser”)一>field(‘id,account.realname)->where(‘status=l AND id>1)->select();

$list role user=Db::name(“AdminRoleUser”)一>where(“role_id', $roleid)->select();

$checks= filter_value($list__role_user.”user_id,,true);

$this->view->assign(‘list,$list user);

$this->view->assign(‘checks,$checks);

return $this->view->fetch();

}

}

代碼分析:當用戶以Get方式提交時,程序執(zhí)行else部分,Get參數(shù)為role_id,程序依次從數(shù)據(jù)庫讀取當前系統(tǒng)非超管用戶(id>l,數(shù)據(jù)庫設計超管賬號id=l)信息到$list_user;讀取當前角色已授權信息到$list_role_user,最后把獲取到的信息以視圖變量的方式指派到對應視圖模板。

當用戶以Post方式提交時,表示用戶是需要保存用戶角色信息,程序執(zhí)行$this->request->isPost()為真的部分,Post參數(shù)形如,array(2){[“id”]_>”3”,[“user_id”]=>array(1){[0]=>”2”}},意為把id=3的角色分配給user_id=2的用戶。首先,程序為先刪除當前角色之前的所有用戶,然后,再把當前Post數(shù)據(jù)簡單處理后一次性新增到role user表中。

(二)RBAC權限的驗證

我們可以把ThinkPHP程序中所有控制器分為兩類,一類是公開性控制器,該類控制器是公開的不需要授權,例如登錄控制器、對外接口性控制器等。另一類是授權控制器,該類控制器必須登錄授權后才能訪問,例如系統(tǒng)權限管理、用戶管理、分組管理等。

系統(tǒng)中怎樣實現(xiàn)授權控制器的訪問攔截的呢?系統(tǒng)在模塊根目錄下設計創(chuàng)建一個通用基類Controller(app\xfadmin\Controller.php),然后在創(chuàng)建授權控制器時,先讓其繼承該基類,這樣就可以把驗證過程放在基類的構造函數(shù)中,只要用戶訪問授權控制器,就會先執(zhí)行驗證程序,從而實現(xiàn)RBAC控制器的實時訪問授權驗證。

下面將具體通過攔截基類Controller部分源碼片段,來簡單分析該驗證過程。

1.用戶UID及ADMrN常量的設置

當用戶正常登錄后,系統(tǒng)會在Session中創(chuàng)建一個用戶UID標識,用于記錄用戶的系統(tǒng)ID號,后續(xù)會通過該UID來獲取用戶獲得的權限樹,同時還會創(chuàng)建一個超級管理員ADMIN標識,用于記錄當前用戶是否是超管賬號。這兩個常量是在通用基類Controller中定義的,因此在所有授權控制器的業(yè)務處理過程中都是可以隨時訪問到的。源碼片段為:

public function____construct(){

defined(‘UID)or define(‘UID,Session::get(Config::get(‘rbac.user_auth_ key)));

defined(‘ADMIN)or define(‘ADMrN,true===Session::get(Config::get(‘rbac.admin_auth_key)));

代碼分析:通過分析以上代碼片段,可知當用戶登錄后系統(tǒng)會把登錄用戶的UID標識和ADMrN標識記錄到系統(tǒng)Session中,每當授權控制器被訪問時,就會實時讀取出來作為驗證用戶權限的標識常量。其中,rbac是權限管理專用配置文件,在模塊文件夾中的extra 中,ThinkPHP引導時會自動引入,在該配置文件中可以動態(tài)配置Session中UID和ADMrN的緩存關鍵字。

2. 用戶登錄驗證和訪問權限驗證

當用戶UID不存在,即表示用戶未登錄,系統(tǒng)會引導用戶跳轉到登錄頁面完成登錄,從而保障了系統(tǒng)資源不被非法訪問。源碼片段為:

public function____construct(){

……

if (null===UID){

$this->notLogin();

} else{

$this->auth();

}

}

當用戶正常登錄,則需要對用戶當前訪問權限進行驗證。以下是auth方法源碼:

protected function auth(){

if (

Config::get(‘rbac.user_ auth on)&&

!in_array($this->request->module(), explode(‘,,Config::get(‘rbac.not_auth_module)))

){

if (?。躌bac::AccessCheck()){

throW new HttpException(403,“沒有權限”);

}

}

}

代碼分析:當rbac配置文件中“user auth on”項打開,并且當前模塊不屬于非授權模塊,則需要進行權限驗證,驗證函數(shù)為\extend\Rbac::AccessCheck方法,該函數(shù)需要傳人待驗證的權限節(jié)點(模塊\控制器\方法)。然后,根據(jù)用戶UID到系統(tǒng)中取出當前用戶的權限列表accessList;最后使用keyExist函數(shù)判斷當前node是否存在于accessList 中,存在則返回true表示當前node被直接授權可以訪問,否則返回false表示不可以訪問??梢姡ㄟ^以上授權驗證機制,使得程序有效地保障了系統(tǒng)用戶不會越權使用權限范圍以外的系統(tǒng)資源。

結束語

訪問控制技術作為國際化標準組織定義的五項標準安全服務之一,是實現(xiàn)信息系統(tǒng)安全的一項重要機制。基于角色的訪問控制( RBAC)是目前流行的先進的安全管理控制方法,解決了傳統(tǒng)的訪問控制方式DAC、MAC 中的一些問題。本文基于RBAC基本模型RBACO,以ThinkPHP和MySQL為開發(fā)環(huán)境,實現(xiàn)了一種適用于小小企業(yè)的權限管理系統(tǒng),能針對系統(tǒng)所有控制器方法進行權限的設置和分配,實現(xiàn)了一種約束型權限分配機制,當用戶在進行權限分配時,僅能分配自己當前所擁有的權限;另外,還實現(xiàn)了一種公共授權機制,簡化了用戶授權的操作復雜度。目前,程序僅實現(xiàn)了RBACO基本模型功能,后續(xù)將需要進一步完善角色層次設計。

參考文獻:

[1]馬林.J2EE企業(yè)級應用系統(tǒng)及其安全框架研究與實現(xiàn)[D].西南交通大學,2007.

[2]劉建圻,曾碧,鄭秀璋.基于RBAC權限管理模型的改進與應用[J].計算機應用,2008,28 (9):2449-2451.

[3]陳波,于冷,肖軍模.計算機系統(tǒng)安全與技術[M].北京:機械工業(yè)出版社,2009.

[4]李蘭崇.基于角色的權限管理訪問控制系統(tǒng)平臺研究與實踐[D].蘭州大學,2009.

西和县| 枞阳县| 吴旗县| 丰县| 双柏县| 象山县| 临洮县| 卢湾区| 永顺县| 明溪县| 武威市| 长垣县| 卓资县| 香港| 大新县| 永昌县| 皋兰县| 沧州市| 交口县| 宁蒗| 锦屏县| 丽江市| 富民县| 岳阳市| 博兴县| 德化县| 湘西| 枝江市| 广平县| 临清市| 华阴市| 武义县| 娱乐| 大新县| 新晃| 宁德市| 民丰县| 邵阳县| 阳东县| 色达县| 祁连县|