1. 程式人生 > >簡單的RBAC基於角色的使用者許可權的實現

簡單的RBAC基於角色的使用者許可權的實現

RBAC基於角色的使用者許可權在實際應用中廣泛使用,尤其是在複雜的多使用者環境下,同一個後臺會用不同角色的使用者,而每個角色使用者所擁有的操作許可權是不同的,RBAC巧妙的解決了這個問題:

這裡先介紹下以前用到過的,THinkphp中內建了RBAC解決方案,這裡不再多說簡單說下實現思路:

要實現不同使用者的許可權操作,關鍵要對許可權分類,哪些類別擁有相同的許可權,哪個使用者屬於這個類,哪個操作對應相對許可權,把這些搞清楚了,RBAC就解決了;這裡涉及到的許可權就是操作,比如管理員類登陸後,新增,修改了文章;新增,修改了文章就是許可權或者叫操作,管理員就是這個類或者組;有了組的概念就必須有成員也稱使用者,假如張三,李四都屬於管理員這個組;那麼他們就擁有了管理員這個類的所有許可權,這裡張三,李四表示我擁有了新增,修改了文章的許可權;理解起來來有點像類的繼承。

這裡舉例來說明,包括四個表:角色【分組】表,許可權【操作】表,使用者表,角色許可權表

角色表:role

id role desc
1 admin 管理員組
2 editor 編輯組
3 user 註冊使用者組


許可權操作表:privilege

id name desc
1 article/list 讀取文章列表
2 article/edit 編輯文章資訊
3 article/create 建立文章內容
4 article/update 更新文章資訊
5 article/delete 刪除文章資訊

使用者表:user

id user role_id bz
1 zfeig 2 編輯組
2 admin 1 管理員組
3 lisi 3 註冊使用者組


角色許可權操作表:role_privilege
role_id privilege_id
1 1,2,3,4,5
2 1,3,4
3 1



思路實現:

使用者登陸後執行每個操作都要檢查操作許可權【可以一個公共函式或者過濾器實現】:


1、使用者登入,獲取使用者表資訊,通過role_id,獲取role_privilege表中的privilege;以陣列方式儲存在session中;


2、使用者執行某個操作,檢查許可權,通過當前操作名稱如index/create,獲取privilege表中對應許可權id,然後對比
使用者session裡面的privilege陣列;如果存在,說明有許可權操作,否則無權操作!

下面看看yii2是怎麼實現的:【轉】

這裡有幾個概念很重要,我簡單用大白話說一下; 
許可權: 
就是指使用者是否可以執行哪些操作。 
如:小張可以發帖、回帖、瀏覽,小紅只能回帖、瀏覽 
角色: 
就是上面說的一組操作的集合。 
如:高階會員有發帖、回帖、刪貼、瀏覽的許可權,普通會員只有回帖、瀏覽的許可權。 
比如小張是高階會員,那麼他就可以執行發帖、回帖、刪貼、瀏覽。而小紅是普通會員,所以它就只能回帖、瀏覽。 
另外角色還可以繼承,中級會員除了普通會員的回帖、瀏覽功能外,還可以發帖。也就是說在普通會員的基礎上又增加了一個發帖的許可權。 
在Yii2.0中

  • yii\rbac: Item  為角色或者許可權的基類,其中用欄位type來標識
  • yii\rbac: Role  為代表角色的類
  • yii\rbac: Permission  為代表權限的類
  • yii\rbac: Assignment  為代表使用者角色或者許可權的類
  • yii\rbac: Rule  為代表角色或許可權能否執行的判定規則表


儲存角色或許可權的表:auth_item 
由於它們的資料儲存在一張表 [auth_item] 裡面,所以他們有一個共同的基類 yii\rbac:Item ,用 $type 欄位來標識是角色還是許可權。 
<ignore_js_op>  
從上面可以看到,上面的三個是使用者角色,下面的五個是許可權。 
角色許可權關聯表:auth_item_child 
上面我們說過,角色是一組許可權的集合,所以還有一個表 [auth_item_child] 用來儲存角色和許可權的關係。 
寫幾個測試資料會看的更明白,現在我們在表auth_item_child中指定它們的關係

   parent                    child
hight_user                  add
hight_user                  edit
hight_user                  delete
......
low_user                     reply
low_user                     view
..................
middle_user                low_user
middle_user                add


hight_user和low_user的關係我們容易理解,middle_user就不一樣了,它指定了另外一個角色: low_user 和一個許可權: add 。 
這個意思就是說 middle_user 包含了low_user的許可權,另外又添加了一個add許可權。 
除了角色可以包含角色外,許可權也是可以包含許可權的。也就是說這個表裡面有三個關係:

  • 角色 包含 許可權
  • 角色 包含 角色
  • 許可權 包含 許可權


如果要得到一個角色的所有的許可權,要做兩方面的查詢,一個是遞迴查詢當前許可權所有的子許可權, 一個是檢視所包含的角色的所有的許可權以及子許可權。 
所以在使用中不建議讓許可權繼承,只讓角色繼承。而且繼承深度也不宜太深。 
最重要的也就是上面這兩個表,具體的程式碼是怎麼實現的會在後面原始碼分析裡面說明。 
使用者角色(許可權)表:[auth_assignment] 
這個表用來儲存使用者的角色或者許可權。 
為什麼是 角色或者許可權 ? 
如上面,給角色指定許可權有兩種辦法

  • 一種是直接給角色指定相應的許可權
  • 一種是讓一個角色繼承(我始終覺的 繼承 這個詞要好於 包含 )自另外一個角色,另外還可以再單獨指定其它的許可權。


所以對使用者而言也有兩種方法。

  • 一種是給使用者指定相應的角色
  • 一種是給使用者指定相應的許可權。


<ignore_js_op>  
這樣一個使用者的許可權包含兩部分,一部分是所指定的角色代表的許可權,一部分就是直接所指定的許可權。 
規則表:[auth_rule] 
一個使用者要執行一個操作除了要看他有沒有這個許可權外,還要看他的這個許可權能不能執行。 
在上面的 表:auth_item 中還有一個欄位: [rule_name] 。這個欄位用來標明這個角色或者許可權能不能成功執行。 
那麼規則這個表裡面的資料是從哪裡來的呢? 
下面這個是規則的基類:

abstract class Rule extends Object
{/**
     * @var string name of the rule
     */
    public $name;
    /**
     * @var integer UNIX timestamp representing the rule creation time
     */
    public $createdAt;
    /**
     * @var integer UNIX timestamp representing the rule updating time
     */
    public $updatedAt;

    /**
     * Executes the rule.
     *
     * @param Item $item the auth item that this rule is associated with
     * @param array $params parameters passed to [[ManagerInterface::allow()]].
     * @return boolean a value indicating whether the rule permits the auth item it is associated with.
     */
    abstract public function execute($item, $params);
}


$name 為規則的名稱。 
也就是說如果要在 規則表:[auth_rule] 中增加一條規則就得要有對應的規則類,並實現方法 abstract public function execute($item, $params) 具體的邏輯來判定$item(角色或者許可權)是否可執行。 
主要的分析也就完成了。關於這一部分的原始碼分析,過幾天也會出來的。 
哪一部分沒說清楚或者還有其它問題都可以留言討論。謝謝各位。喜歡的就頂一下。 
原文連結: http://www.yiifans.com/forum.php?mod=viewthread&tid=74#lastpost