通用數據許可權的思考與設計
作者:_liuxx
http://cnblogs.com/liuyh/p/9774998.html
1、數據許可權概述
1.1、什麼是數據許可權?
數據許可權是指對系統用戶進行數據資源可見性的控制,通俗的解釋就是:符合某條件的用戶只能看到該條件下對應的數據資源
。那麼最簡單的數據許可權大概就是:用戶只能看到自己的數據。而在正式的系統環境中,會有很多更為複雜的數據許可權需求場景,如:
- 領導需要看到所有下屬員工的客戶數據,員工只能看自己的客戶數據;
- 經理A能看到所有企業客戶,經理B只能看到年銷售額小於1000萬的企業客戶;
- 角色A能看到全國的產品數據,角色B只能看到上海的產品數據;
上述這些需求,使用硬編碼也是可以實現的,但是在業務快速發展的過程中,類似這種數據許可權需求會越來越多,如果全部採用硬編碼的方式,無疑會給我們帶來巨大的開發和維護壓力。
1.2、要素分析
從當前登錄用戶的角度來說,數據許可權的定義可以解釋為:當前登錄的用戶只能看到該用戶許可權範圍內的數據資源
。由此可以分析出數據許可權控制中幾個關鍵要素:
- 主體,即當前登錄用戶。領導、角色等概念可翻譯為當前登錄用戶是否是領導,是否擁有某角色。
- 數據資源。即受管控系統數據。
- 條件規則。即當前登錄用戶對於某特定的數據資源適用的條件。
2、數據許可權設計
理論上來說,用戶在訪問受控的系統數據時,獲取用戶對該數據資源適用的條件規則,並將該條件規則解析為SQL查詢語句即可實現對數據的許可權控制。但是在實現過程中,還是會有很多難點,譬如當前登錄用戶適用下列規則:
客戶數據:[客戶經理] [包含於] [下屬人員]
產品數據:[銷售地區] [等於] [上海]訂單數據:([產品銷售地區] [等於] [上海])[並且] ([客戶市場經理] [包含於] [下屬人員])
思考如下問題:
[客戶經理] [包含於] [下屬人員]
如何解析為SQL語句?多表聯合查詢時又該如何處理?[下屬人員]
由系統根據當前登錄用戶計算而來,上海
由管理員後臺選擇。兩種方式如何兼容?- 對於複雜多變的組合條件,應該如何設計?
- 如何確定當前查詢應該應用哪些條件規則?
- 一個用戶擁有多個角色,不同角色對於同一個規則設置不同的值應該如何處理?
2.1、規則元
名詞定義:規則元。在本文是指單個獨立的數據規則定義,不同用戶對規則元可設置具體的規則過濾值,該值用作數據查詢時的篩選條件。上述規則中[客戶經理]
,[銷售地區]
都屬於規則元。
2.2、規則元配置
1.規則元名稱的配置。一個表中哪些欄位可以進行規則設置,以及規則元名稱如何與表欄位關聯。(如上述規則中[客戶經理]
,[銷售地區]
),比較容易想到的方法是通過配置文件維護規則名稱與資料庫欄位之間的關係。
2.規則元Value數據源的配置。如上述規則中的[下屬人員]
,[上海]
,不難發現規則元Value來源有三種情況:
- 後臺管理人員輸入。
- 系統提供數據源,後臺管理人員選擇。如:所在地區
[上海]
- 系統提供數據。如:
[下屬人員]
配置文件可以實現數據規則的配置需求,但是當規則元越來越多時,維護配置文件就會變得麻煩起來,我們是否可以效仿spring-boot取代spring-mvc的做法,使用註解來代替配置呢?每一條數據規則最終都會落到對資料庫欄位的控制,而現在絕大部分系統都會有一個Model層對應到資料庫中的表,於是腦補出一個絕佳的規則元配置方式:
@TableName("test")
public class TestModal extends AbstractModel {
@DataRule(name = "規則元名稱")
private String name;
}
@DataRule
註解源碼如下:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataRule {
/**
* 規則元名稱
*/
String name() default "";
/**
* 規則元值來源類型
*/
RuleSourceStrategy strategy() default RuleSourceStrategy.TEXT;
/**
* 當數據來源是用戶選擇時{@code RuleSourceStrategy.CHOICE}數據地址
*/
String url() default "";
/**
* 當數據來源是系統提供時{@code RuleSourceStrategy.SYSTEM}提供器類名
*/
Class<? extends IDataRuleProvider> provider() default NullDataRuleProvider.class;
}
系統啟動時,將規則元配置信息(名稱、對應數據表、對應欄位、值來源類型,值來源url,值來源提供者類名等)同步至資料庫。數據表簡單設計如下圖: