在之前寫過一篇關于菜單權限系統的設計,是以為了完善整個權限系統的模型,決定把資料權限也做一個總結。菜單權限管理系統
目标
實作對資料的權限控制。簡單的來說,就是決定誰可以操作(增删改查)哪些資料。
該權限模型的适用範圍
該模型目前在一些常用的管理平台得到的驗證與實施,目前已應用在多個公司産品中,主要場景是CRM類項目。
核心難點
資料權限的主要難度在于查詢的性能、授權、鑒權,字段級别的控制。
比如在百萬級别規模時,mysql如何實作秒級别的查詢?
場景介紹:在之前設計該權限模型時,我們的項目遇到了一個核心的難題,sql的查詢速度非常的緩慢!!!一個sql可能高達10S+。這對于使用者而言,是無法接受的。是以我們嘗試去優化sql的表設計,索引的優化,但是最終結果都擺陣下來。主要的問題是我們并沒有足夠抽象資料,導緻百萬級别的資料下,sql非常緩慢。這裡面占時不需要考慮分庫分表(百萬級别的規模不足以使用該手段)。
百萬級别的資料權限怎麼授予使用者?
場景介紹:面對如此大的資料量,如何授權使用者權限呢?總不能是逐個配置設定的!!!
如何快速高效的進行資料鑒權呢?
場景介紹:這麼大的資料量,在程式中不容易處理,必須借助于資料庫的高效查詢方案,但是怎麼實作呢?
如何實作字段級别的權限控制?
場景介紹:字段級别的權限怎麼控制?控制sql的生成邏輯?還是怎麼處理呢?
權限模型的抽象
有了那麼多的問題,我們先從權限模型入手,我們必須高度抽象化我們的權限系統,才有機會做到。
下面我們直接貼出一個圖,介紹該模型的一些核心概念
我們根據上圖所示,可以觀察到下面的幾個元素,分别是:權限實體,部門,角色,菜單權限。
其中菜單權限參考上面的連結
權限實體:這個是該權限模型的核心元素,也就是我們需要系統控制的資料。比如客戶,訂單,管道,區域等。
部門:這個簡單,就是一般的部門組織結構
角色:抽象的實體,用于快速配置設定權限相同權限給一批使用者,與菜單權限的角色概念一緻。
權限的查詢模型
在上面的圖中,不知道大家是否看到了一條sql
select xxx from xx_table where account in (xxx) and product_group in (xxx) and country in (xxx)
沒錯,這就是該模型的查詢模型。其中account,product_group,country代表需要做權限控制的權限實體。
在這裡面隻是一個簡單的模型,如果account或者country等資料量足夠大時,我們會發現mysql in查詢是會出現非常嚴重的查詢性能的。比如account資料量規模為100W時...
引入部門組織結構,突破資料量的限制
還是看上圖,我們有一個部門組織結構,我們可以想象下,比如總經理,自然是可以檢視所有部門的資料。假設A部門經理,可以檢視A部門以及子部門的資料。如果是普通的員工,隻能檢視自己賬号下的資料。
下面我們給出一個部門組織結構圖,并且給每個部分标志一個key,key的生成規則如下
1.根部門的key為數字10
2.根部門的直屬部門的key為10 001,10 002,10 003...以此類推
3.其他的key生成邏輯和步驟2相同,唯一不同的就是key的長度變長了,比如:10 001 001,10 001 002
這裡面我們給部門打上如下的key,為了友善介紹,我們還是貼圖檔
有了該模型,我們結合mysql的前置查詢索引的特性(org like 'xxxx%')
where org like '10%'
org like '10001%'
org like '10002%'
上面的查詢,在mysql下,200W的資料規模,可以實作1S内響應!!!
如何授權
解決了查詢的性能,其實授權也就很簡單了。
授權我們一般根據員工的崗位來設定,普通員工,部門經理
普通員工:不需要單獨授權,直接綁定員工工号即可
部門經理:設定該員工可以檢視的部門(支援多個)
如何鑒權
鑒權和授權一般是互相的一個過程
1.判斷該員工是否為部門經理
2.如果是,取出部門的key
3.添加到sql中,使用mysql前置like查詢資料
字段權限的控制
字段權限的控制,我們直接針對接口程式設計,不要針對sql程式設計。
比如擷取員工清單:我們隻需要控制輸出的字段屬性即可。
為啥不針對sql程式設計?因為sql需要考慮各種join,字段是否缺失,關聯的内容存儲在其他表等情況
資料庫的實作
1.識别權限實體
2.給權限實體加上一個工号字段,一個部門字段,比如:emp_id,org_key
3.查詢時,先擷取員工的角色權限,如果是部門經理,那麼擷取對應的key清單
4.建構sql,加入部門或者工号的sql片段
- org_key lik '10 001%' or org_key like '10 002%',這是部門的sql
- emp_id = 'xxx',這是普通員工的sql
總結
設計好一個權限系統,說難不難,但是也不簡單。
主要的難點在于
1.識别出你需要控制的資料(權限實體)
2.高效的查詢效率與sql的索引相結合(這裡面使用部門key與sql的前置查詢)
應用于擴充
該模型設計簡單,具備一定的普遍性,是以在設計時,我們可以根據不同的系統去進行演進與擴充。大家有興趣的可以思考下