簡單的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