按照計劃本暑假進行點名系統的大型更新,其一重頭戲就是強化權限體系,加入角色的概念。如何優雅、高效地實現權限認證成了一個棘手的問題。參考網上部分文章,初步計劃應用下面的設計。在此整理記錄一下。
基本思路
“角色”是權限的最小單位,所有用戶必須關聯角色,不允許直接賦予權限。一個用戶可以關聯多個角色,其權限取并集。
每個角色可以包含各種權限。
用“位”表示權限
最簡單粗暴的權限記錄形式就是列表,例如如下一個用于記錄權限的數據表:
[Table:permission]
Id | UserName | Permission |
---|---|---|
0 | aaa | LEAVE_BROWSE |
1 | aaa | LEAVE_ADD |
2 | aaa | LEAVE_DEL |
3 | bbb | LEAVE_BROWSE |
此種記錄方法雖簡單直觀,但冗余數據過多,每一次判斷權限都需要查詢一遍整個表,性能差,尤其在用戶與權限種類較多的時候。
用“位”表示權限的理論基礎是超遞增序列:1,2,4,8,16……,即:2^n(n>=0)。此數列有這樣一個特性:拼出的任意一個和數一定可以由這個序列中的一些數構成,且構成方法唯一。例如:20=16+4且只有16和4可以拼出20.借助這個特性我們可以用來表示權限。
首先建立權限內容與編號的對應關系(可寫為常量或xml或其他任意類型):
編號(為2^n) | 說明 |
---|---|
1 | 讀取請假列表 |
2 | 添加請假列表 |
4 | 刪除請假列表 |
假設用戶aaa同時具有讀取與添加請假列表的權限,只需要將他的權值設為1+2=3即可。
如此一來,上述的權限表甚至可以刪掉,直接集成在用戶表里就夠了:
[Table:user]
UserName | Permission | ...OtherFields |
---|---|---|
aaa | 7 | ... |
bbb | 1 | ... |
…… | …… | …… |
判斷權限
如果我們知道用戶aaa的權值為3,如何判斷他是否具有某一權限呢?
很簡單,只需要進行位與運算即可。若結果不為0則表示具有此權限。
例如:
3D=011B;1D=001B;2D=010B;4D=100B
011B & 010B = 010B ≠ 0,則具有添加權限。
011B & 100B = 000B,則不具有刪除權限。
增加權限
那么如果在已有權限基礎上增加一個權限呢?
只需進行位或即可。
例如:
011B | 100B = 111B = 7D
在讀取與添加的基礎上增加了刪除權限。
同時發現7=1+2+4,與上述超遞增序列的定義是一致的
刪除權限
當然,有時我們也需要剝奪某人的一些權限。
只要與上按位取反即可。
例如:
111B &~ 010B = 101B = 5D
此時剝奪了添加權限,只剩讀取、刪除權限了。
范圍問題
不難看出,此處的權值是個整數,一般情況下應該會習慣性地用int存儲,這樣問題就來了,int一般情況下只能表示2^32,如果權限種類大于32該如何是好。
權限分組
未完待續。。。