一種通用型的許可權系統設計
30 Sep 2018 - h3l
[+] Author: h3l [+] Team: n0tr00t security team [+] From: https://www.n0tr00t.com [+] Create: 2018-09-30
先簡單看一下簡單的表結構以及表關係。
+----------+parent_id & child_id+--------------+ | Relation | ------------------------ | Organization | +----------++--------------+ | | org_id | +----------+user_id+--------------+ |User| ------------------------ | UserPosition | +----------++--------------+ | | group_id | +-----+service_id & api_id+----------+group_id & service_id+--------------+ | Api | ---------------------- | Service| ------------------------ |Group| +-----++----------++--------------+
表解釋
-
使用者相關
-
User
用於儲存使用者資訊,主要欄位為id
使用者資訊等
-
-
組織相關
-
Organization
用於儲存組織架構中的單個組織,主要欄位為id
,name
等等 -
Relation
用於儲存組織架構中的組織間關係,主要欄位為parent_id
,child_id
-
-
群組相關
-
Group
用於儲存群組資訊,主要欄位為id
群組名等 -
Service
用於儲存服務資訊,主要欄位為id
服務名稱等 -
Api
用於儲存介面資訊,主要欄位為id
,url_name,
app_name`等 -
另外還有兩張表用於儲存
Group
與Service
的多對多關係以及Service
與Api
的多對多關係
-
-
將上述關係組織到一起
-
UserPosition
記錄一個人在哪些組織上屬於什麼群組,主要欄位有user_id
,group_id
,org_id
-
概述
上述的那麼多表,其實只是解決了一個問題『一個人 在什麼範圍 能做什麼事情 』。
- 一個人 即 使用者相關的表
- 什麼範圍 即 組織相關的表
- 什麼事情 即 群組相關的表
使用者相關
即許可權系統中的使用者,並無複雜概念
組織相關
現實生活中的組織架構是一個類似樹形的不規則結構,如下圖所示
+----------+ +------------- |root| ------+ |+----------+| ||| ||| vv| +----------++----------+| +------------- |mid_a||mid_b|| |+----------++----------+| |||| |||| vvvv +----------++----------++----------++----------+ | bottom_a || bottom_b || bottom_c || bottom_d | +----------++----------++----------++----------+
如果是儲存樹形結構,第一反應可能是在每個節點記錄一個parent_id
。這是最簡單的做法,但是在查詢某個節點的所有子節點的時候卻是效率最差的做法。
這裡我們採用的方法是單獨拿一張關係表記錄父節點到所有子節點的資料。這樣做的好處是查詢效率非常高,只是在插入資料的時候稍微慢一點,但是考慮到我們的應用是讀大於寫,所以這樣做並無不妥。按照上述說法,則可以用下表表示下圖。
+------+ +------------- | root | ------+ |+------+| || || v| +----------+| +------------- |mid_a|| |+----------+| ||| ||| vvv +----------++----------++----------+ | bottom_a || bottom_b || bottom_d | +----------++----------++----------+
父節點 | 子節點 |
---|---|
root | mid_a |
root | bottom_a |
root | bottom_b |
root | bottom_d |
mid_a | bottom_a |
mid_a | bottom_b |
tip: 如果為了方便,可以為每個節點插入一條父節點和子節點均為自己的記錄。
該方法並非獨創,詳細的分析該方法以及與其他方法的對比可參見ofollow,noindex" target="_blank">https://www.slideshare.net/billkarwin/models-for-hierarchical-data
群組相關
在群組這部分的設計中,包含了五張表。但是關鍵的概念僅為Api
,Service
,Group
, 其實這樣設計會稍顯複雜。那我們為什麼要這樣設計呢?
最重要的原因是將開發與產品/運營間有效的隔離開。
Api
表記錄的是系統中所有的介面,這是開發需要維護的部分。
Service 表記錄的是系統中的功能點,這是需要產品/運用同開發共同維護的部分
- 產品需要提供要在管理後臺中功能點的管理粒度,比如說是:使用者管理(包含使用者檢視,使用者刪除,使用者修改等功能)還是使用者檢視?
- 開發則需要將 Api 中與產品定義好的 Service 關聯起來。
Group
表記錄的是系統中的群組,這是需要產品維護的部分,同時產品需要維護群組與功能點的關係。
ps:Api
表中的app_name
與url_name
是為了保證在不同系統中相同的url_可能會衝突的情況
pss:仔細想想,Api 表中的api
是不是可以偷懶的整個一個系統只用同一個呢?甭管你有多少介面,全部一把梭,都用同一個api
。當然可以了,只要能滿足需求,api
怎麼記錄完全看你自己,這也是本系統靈活的原因。
n more thing
- 是不是可以將組織架構依賴公司內部的 hr 系統?這樣公司組織架構變動的時候就不用手動維護了。
- 是不是可以將使用者表也通過對接公司內部的 hr 系統來完成呢?比如對接一個 oauth,這樣這個人離職/入職也不用維護這部分內容了。
- 使用者崗位部分是不是可以通過上一步介入的 oauth 拿到使用者的崗位資訊?通過一個員工崗位與系統內群組的對應關係的表,是不是就可以自動的讓使用者登入後擁有相應許可權了?
- 使用者崗位部分是不是可以支援手動新增崗位?只要通過新增一個欄位表示這個崗位是自動同步的還是手動加入的,自動同步的每次登入的時候重新整理,非自動同步的只能手動修改。這樣誰誰誰要臨時加一個許可權,也不用頭疼了。