RBAC角色權限模型設計

關於網站用戶權限管理的設計模型。

我根據業內的一些標準和案例整理出一套RBAC用戶權限設計模型文檔。

希望對大家在系統設計時有幫助。

有其他見解請指教。RBAC權限模型設計

 

在 RBAC社區的不斷努力下,RBAC在 2004年 2月被美國國家標準委員會(ANSI)和  IT國際標準委員會(INCITS)接納爲ANSI INCITS 359-2004標準。       RBAC標準包括兩個主要部分:RBAC參考模型和RBAC功能描述。

 

RBAC 是英文(Role-Based Access Control)的縮寫,也就是基於角色的訪問控制。RBAC 的定義比較晦澀,我就以比較生動的形式來闡述什麼是 RBAC。


--------------------------------------------------------------------------------

 

ATM 機的一天

假設有一臺 ATM(自動提款機)放在街邊,我們來看看這個 ATM 度過的一天。

1.    早上,有一個傢伙走到 ATM 面前,對着機器說:“芝麻開門,芝麻開門,給我 100 塊!”。很顯然 ATM 不會有任何動作。失望之餘,這個傢伙踢了 ATM 一腳走了。

2.    中午,一位漂亮的 Office lady 走到 ATM 機面前,放入她的信用卡,輸入密碼後,取出了 1200 塊錢。當然,這些錢很快就會變成一件衣服或是化妝品。

3.    下班時分,銀行的工作人員來到 ATM 機器面前,放入一張特製的磁卡,然後輸入密碼。從中查詢到 ATM 機器內還有充足的現金,無需補充。所以他很高興的開着車去下一臺 ATM 機器所在地了。

現在我們要開發一臺具有同樣功能的 ATM 機,應該怎麼做呢?

首先,我們的 ATM 機不能讓人隨便取錢,不然銀行會破產的。接下來,ATM 機需要一個讓人們放入磁卡並輸入密碼的設備。人們放入磁卡並輸入密碼後,ATM 機還要能夠判斷這張磁卡的卡號和密碼是否有效,並且匹配。之後,ATM 機必須判斷磁卡的卡號屬於哪種類型,如果是信用卡,那麼則顯示查詢賬戶餘額和取款的界面。如果是特製的磁卡,則顯示 ATM 機內的現金餘額。


--------------------------------------------------------------------------------

 

ATM 與 RBAC

上面的例子顯得有點荒誕,但是卻是一個典型的基於角色的訪問控制。

1.    對於沒有磁卡或者輸入了錯誤密碼的用戶,一律拒絕服務,也就是不允許進行任何其他操作;

2.    如果輸入了正確的密碼,必須判斷用戶輸入哪一種類型,並提供相應的服務界面;

3.    如果用戶嘗試訪問自己不能使用的服務,那麼要明確告訴用戶這是不可能的。

這個流程中,一共出現了兩種角色:信用卡用戶和管理卡用戶。而那些沒有磁卡的用戶,都屬於沒有角色一類。RBAC 要能夠工作,至少需要兩個數據:角色信息和訪問控制表。

角色信息通常是指某個用戶具有的角色,例如你持有一張信用卡,那麼你就具有“信用卡用戶”這個角色。如果你持有一張管理卡,那麼你就具有“管理卡用戶”這個角色。如果你既沒有信用卡,又沒有管理卡,那麼你就沒有上述兩種角色。

有了角色信息,RBAC 系統還需要一個訪問控制表。訪問控制表(Access Control Table)是一組數據,用於指出哪些角色可以使用哪個功能,哪些角色不能使用哪個功能。例如在 ATM 機中,具有“信用卡用戶”角色,就可以使用查詢賬戶餘額和取款兩項功能;而具有“管理卡用戶”角色,就可以使用查詢 ATM 機內現金餘額的動能。

我們來模擬一次 ATM 機的操作:

1.    唐雷有一張信用卡,他放入 ATM 機並輸入了正確的密碼。這時,他被 ATM 機認爲具有“信用卡用戶”角色。

2.    根據上面的判斷結果,ATM 機顯示了一個操作界面,上面有查詢賬戶餘額和取款兩項操作按鈕。

3.    唐雷按下了“查詢賬戶餘額”按鈕,ATM 機的查詢賬戶餘額功能被調用。

4.    在查詢賬戶餘額功能中,再次檢查用戶的角色信息,確定他可以使用這個功能。

5.    進行一系列操作,然後將唐雷信用卡賬戶上的餘額數字顯示到屏幕上。

6.    唐雷很鬱悶他的信用卡又透支了,悻悻然取出卡走人了。這時 ATM 自動清除當前的角色信息,爲下一次操作做好準備。

從上面可以看出,RBAC 充當了系統的一道安全屏障。所有的操作都需要進過 RBAC 驗證過後才能使用。這樣充分保證了系統的安全性。


--------------------------------------------------------------------------------

 

RBAC 概念

在 FleaPHP 的 RBAC 組件中,只有下列幾項概念需要理解:

用戶:應用程序的使用者;
角色:一個名字,可以爲用戶指定多個角色(0-n);
訪問控制表(ACT):一個數組,用來指明哪些功能可以被哪些角色訪問或者限制訪問。
除了上述三個概念,要想 RBAC 系統能夠正常工作,還需要用戶信息管理器、角色信息管理器和訪問控制器三個部件。

用戶信息管理器:提供用戶信息的存儲、查詢服務,以及爲用戶指定角色信息;
角色信息管理器:提供角色信息的存儲和查詢服務
訪問控制器:根據角色信息和訪問控制表進行驗證
 

 

 

 

 

 

FleaPHP核心RBAC文件:

00001 <?php

00003 // FleaPHP Framework

00004 //

00005 // Copyright (c) 2005 - 2007 FleaPHP.org (www.fleaphp.org)

00006 //

00007 // 許可協議,請查看源代碼中附帶的 LICENSE.txt 文件,

00008 // 或者訪問 http://www.fleaphp.org/ 獲得詳細信息。

00010

00030 class FLEA_Rbac

00031 {

00037     var $_sessionKey = 'RBAC_USERDATA';

00038

00044     var $_rolesKey = 'RBAC_ROLES';

00045

00051     function FLEA_Rbac()

00052     {

00053         $this->_sessionKey = FLEA::getAppInf('RBACSessionKey');

00054         if ($this->_sessionKey == 'RBAC_USERDATA') {

00055             trigger_error(_ET(0x0701005), E_USER_WARNING);

00056         }

00057     }

00058

00065     function setUser($userData, $rolesData = null)

00066     {

00067         if ($rolesData) {

00068             $userData[$this->_rolesKey] = $rolesData;

00069         }

00070         $_SESSION[$this->_sessionKey] = $userData;

00071     }

00072

00078     function getUser()

00079     {

00080         return isset($_SESSION[$this->_sessionKey]) ?

00081                 $_SESSION[$this->_sessionKey] :

00082                 null;

00083     }

00084

00088     function clearUser()

00089     {

00090         unset($_SESSION[$this->_sessionKey]);

00091     }

00092

00098     function getRoles()

00099     {

00100         $user = $this->getUser();

00101         return isset($user[$this->_rolesKey]) ?

00102                 $user[$this->_rolesKey] :

00103                 null;

00104     }

00105

00111     function getRolesArray()

00112     {

00113         $roles = $this->getRoles();

00114         if (is_array($roles)) { return $roles; }

00115         $tmp = array_map('trim', explode(',', $roles));

00116         return array_filter($tmp, 'trim');

00117     }

00118

00127     function check(& $roles, & $ACT)

00128     {

00129         $roles = array_map('strtoupper', $roles);

00130         if ($ACT['allow'] == RBAC_EVERYONE) {

00131             // 如果 allow 允許所有角色,deny 沒有設置,則檢查通過

00132             if ($ACT['deny'] == RBAC_NULL) { return true; }

00133             // 如果 deny 爲 RBAC_NO_ROLE,則只要用戶具有角色就檢查通過

00134             if ($ACT['deny'] == RBAC_NO_ROLE) {

00135                 if (empty($roles)) { return false; }

00136                 return true;

00137             }

00138             // 如果 deny 爲 RBAC_HAS_ROLE,則只有用戶沒有角色信息時才檢查通過

00139             if ($ACT['deny'] == RBAC_HAS_ROLE) {

00140                 if (empty($roles)) { return true; }

00141                 return false;

00142             }

00143             // 如果 deny 也爲 RBAC_EVERYONE,則表示 ACT 出現了衝突

00144             if ($ACT['deny'] == RBAC_EVERYONE) {

00145                 FLEA::loadClass('FLEA_Rbac_Exception_InvalidACT');

00146                 __THROW(new FLEA_Rbac_Exception_InvalidACT($ACT));

00147                 return false;

00148             }

00149

00150             // 只有 deny 中沒有用戶的角色信息,則檢查通過

00151             foreach ($roles as $role) {

00152                 if (in_array($role, $ACT['deny'], true)) { return false; }

00153             }

00154             return true;

00155         }

00156

00157         do {

00158             // 如果 allow 要求用戶具有角色,但用戶沒有角色時直接不通過檢查

00159             if ($ACT['allow'] == RBAC_HAS_ROLE) {

00160                 if (!empty($roles)) { break; }

00161                 return false;

00162             }

00163

00164             // 如果 allow 要求用戶沒有角色,但用戶有角色時直接不通過檢查

00165             if ($ACT['allow'] == RBAC_NO_ROLE) {

00166                 if (empty($roles)) { break; }

00167                 return false;

00168             }

00169

00170             if ($ACT['allow'] != RBAC_NULL) {

00171                 // 如果 allow 要求用戶具有特定角色,則進行檢查

00172                 $passed = false;

00173                 foreach ($roles as $role) {

00174                     if (in_array($role, $ACT['allow'], true)) {

00175                         $passed = true;

00176                         break;

00177                     }

00178                 }

00179                 if (!$passed) { return false; }

00180             }

00181         } while (false);

00182

00183         // 如果 deny 沒有設置,則檢查通過

00184         if ($ACT['deny'] == RBAC_NULL) { return true; }

00185         // 如果 deny 爲 RBAC_NO_ROLE,則只要用戶具有角色就檢查通過

00186         if ($ACT['deny'] == RBAC_NO_ROLE) {

00187             if (empty($roles)) { return false; }

00188             return true;

00189         }

00190         // 如果 deny 爲 RBAC_HAS_ROLE,則只有用戶沒有角色信息時才檢查通過

00191         if ($ACT['deny'] == RBAC_HAS_ROLE) {

00192             if (empty($roles)) { return true; }

00193             return false;

00194         }

00195         // 如果 deny 爲 RBAC_EVERYONE,則檢查失敗

00196         if ($ACT['deny'] == RBAC_EVERYONE) {

00197             return false;

00198         }

00199

00200         // 只有 deny 中沒有用戶的角色信息,則檢查通過

00201         foreach ($roles as $role) {

00202             if (in_array($role, $ACT['deny'], true)) { return false; }

00203         }

00204         return true;

00205     }

00206

00214     function prepareACT($ACT)

00215     {

00216         $ret = array();

00217         $arr = array('allow', 'deny');

00218         foreach ($arr as $key) {

00219             do {

00220                 if (!isset($ACT[$key])) {

00221                     $value = RBAC_NULL;

00222                     break;

00223                 }

00224

00225                 if ($ACT[$key] == RBAC_EVERYONE || $ACT[$key] == RBAC_HAS_ROLE

00226                     || $ACT[$key] == RBAC_NO_ROLE || $ACT[$key] == RBAC_NULL) {

00227                     $value = $ACT[$key];

00228                     break;

00229                 }

00230

00231                 $value = explode(',', strtoupper($ACT[$key]));

00232                 $value = array_filter(array_map('trim', $value), 'trim');

00233                 if (empty($value)) { $value = RBAC_NULL; }

00234             } while (false);

00235             $ret[$key] = $value;

00236         }

00237

00238         return $ret;

00239     }

00240 }

 

 

 

 

 

RBAC角色權限設置文件

array(

    'allow' => '允許訪問該控制器的角色名',

    'deny' => '禁止訪問該控制器的角色名',

 

    'actions' => array(

        '動作名' => array(

            'allow' => '允許訪問該動作的角色名',

            'deny' => '禁止訪問該動作的角色名',

        ),

        // .... 更多動作

    ),

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

基於RBAC模型的通用權限管理系統的設計

(數據模型)的擴展

 

1 RBAC模型
       訪問控制是針對越權使用資源的防禦措施。基本目標是爲了限制訪問主體(用戶、進程、服務等)對訪問客體(文件、系統等)的訪問權限,從而使計算機系統在合法範圍內使用;決定用戶能做什麼,也決定代表一定用戶利益的程序能做什麼[1]。
        企業環境中的訪問控制策略一般有三種:自主型訪問控制方法、強制型訪問控制方法和基於角色的訪問控制方法(RBAC)。其中,自主式太弱,強制式太強,二者工作量大,不便於管理[1]。基於角色的訪問控制方法是目前公認的解決大型企業的統一資源訪問控制的有效方法。其顯著的兩大特徵是:1.減小授權管理的複雜性,降低管理開銷;2.靈活地支持企業的安全策略,並對企業的變化有很大的伸縮性。
       NIST(The National Institute of Standards and Technology,美國國家標準與技術研究院)標準RBAC模型由4個部件模型組成,這4個部件模型分別是基本模型RBAC0(Core RBAC)、角色分級模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和統一模型RBAC3(Combines RBAC)[1]。RBAC0模型如圖1所示。
         a. RBAC0定義了能構成一個RBAC控制系統的最小的元素集合。在RBAC之中,包含用戶users(USERS)、角色roles(ROLES)、目標objects(OBS)、操作operations(OPS)、許可權permissions(PRMS)五個基本數據元素,權限被賦予角色,而不是用戶,當一個角色被指定給一個用戶時,此用戶就擁有了該角色所包含的權限。會話sessions是用戶與激活的角色集合之間的映射。RBAC0與傳統訪問控制的差別在於增加一層間接性帶來了靈活性,RBAC1、RBAC2、RBAC3都是先後在RBAC0上的擴展。
         b. RBAC1引入角色間的繼承關係,角色間的繼承關係可分爲一般繼承關係和受限繼承關係。一般繼承關係僅要求角色繼承關係是一個絕對偏序關係,允許角色間的多繼承。而受限繼承關係則進一步要求角色繼承關係是一個樹結構。
        c. RBAC2模型中添加了責任分離關係。RBAC2的約束規定了權限被賦予角色時,或角色被賦予用戶時,以及當用戶在某一時刻激活一個角色時所應遵循的強制性規則。責任分離包括靜態責任分離和動態責任分離。約束與用戶-角色-權限關係一起決定了RBAC2模型中用戶的訪問許可。
        d. RBAC3包含了RBAC1和RBAC2,既提供了角色間的繼承關係,又提供了責任分離關係。

 2核心對象模型設計

      根據RBAC模型的權限設計思想,建立權限管理系統的核心對象模型.對象模型中包含的基本元素主要有:用戶(Users)、用戶組(Group)、角色(Role)、目標(Objects)、訪問模式(Access Mode)、操作(Operator)。主要的關係有:分配角色權限PA(Permission Assignment)、分配用戶角色UA(Users Assignmen描述如下:

       a .控制對象:是系統所要保護的資源(Resource),可以被訪問的對象。資源的定義需要注意以下兩個問題:
       1.資源具有層次關係和包含關係。例如,網頁是資源,網頁上的按鈕、文本框等對象也是資源,是網頁節點的子節點,如可以訪問按鈕,則必須能夠訪問頁面。
       2.這裏提及的資源概念是指資源的類別(Resource Class),不是某個特定資源的實例(Resource Instance)。資源的類別和資源的實例的區分,以及資源的粒度的細分,有利於確定權限管理系統和應用系統之間的管理邊界,權限管理系統需要對於資源的類別進行權限管理,而應用系統需要對特定資源的實例進行權限管理。兩者的區分主要是基於以下兩點考慮:
        一方面,資源實例的權限常具有資源的相關性。即根據資源實例和訪問資源的主體之間的關聯關係,纔可能進行資源的實例權限判斷。 例如,在管理信息系統中,需要按照營業區域劃分不同部門的客戶,A區和B區都具有修改客戶資料這一受控的資源,這裏“客戶檔案資料”是屬於資源的類別的範疇。如果規定A區只能修改A區管理的客戶資料,就必須要區分出資料的歸屬,這裏的資源是屬於資源實例的範疇。客戶檔案(資源)本身應該有其使用者的信息(客戶資料可能就含有營業區域這一屬性),才能區分特定資源的實例操作,可以修改屬於自己管轄的信息內容。
        另一方面,資源的實例權限常具有相當大的業務邏輯相關性。對不同的業務邏輯,常常意味着完全不同的權限判定原則和策略。
        b.權限:對受保護的資源操作的訪問許可(Access Permission),是綁定在特定的資源實例上的。對應地,訪問策略(Access Strategy)和資源類別相關,不同的資源類別可能採用不同的訪問模式(Access Mode)。例如,頁面具有能打開、不能打開的訪問模式,按鈕具有可用、不可用的訪問模式,文本編輯框具有可編輯、不可編輯的訪問模式。同一資源的訪問策略可能存在排斥和包含關係。例如,某個數據集的可修改訪問模式就包含了可查詢訪問模式。
        c.用戶:是權限的擁有者或主體。用戶和權限實現分離,通過授權管理進行綁定。
        d.用戶組:一組用戶的集合。在業務邏輯的判斷中,可以實現基於個人身份或組的身份進行判斷。系統弱化了用戶組的概念,主要實現用戶(個人的身份)的方式。
        e.角色:權限分配的單位與載體。角色通過繼承關係支持分級的權限實現。例如,科長角色同時具有科長角色、科內不同業務人員角色。
        f.操作:完成資源的類別和訪問策略之間的綁定。
        g.分配角色權限PA:實現操作和角色之間的關聯關係映射。
        h.分配用戶角色UA:實現用戶和角色之間的關聯關係映射。

 該對象模型最終將訪問控制模型轉化爲訪問矩陣形式。訪問矩陣中的行對應於用戶,列對應於操作,每個矩陣元素規定了相應的角色,對應於相應的目標被准予的訪問許可、實施行爲。按訪問矩陣中的行看,是訪問能力表CL(Access Capabilities)的內容;按訪問矩陣中的列看,是訪問控制表ACL(Access Control Lists)的內容。
數據模型圖如下:

 


 希望各位多提意見 ,再完善

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/wssxy/archive/2008/03/28/2224954.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章