數據權限就該這麼實現(設計篇)
大家好,我是 飄渺!
在項目實際開發中我們不光要控制一個用户能訪問哪些資源,還需要控制用户只能訪問資源中的某部分數據。
控制一個用户能訪問哪些資源我們有很成熟的權限管理模型即RBAC,但是控制用户只能訪問某部分資源(即我們常説的數據權限)使用RBAC模型是不夠的,本文我們嘗試在RBAC模型的基礎上融入數據權限的管理控制。
首先讓我們先看下RBAC模型。
RBAC模型
RBAC是Role-BasedAccess Control的英文縮寫,意思是基於角色的訪問控制。
RBAC事先會在系統中定義出不同的角色,不同的角色擁有不同的權限,一個角色實際上就是一組權限的集合。而系統的所有用户都會被分配到不同的角色中,一個用户可能擁有多個角色。使用RBAC可以極大地簡化權限的管理。
RBAC模型還可以細分為RBAC0,RBAC1,RBAC2,RBAC3。這裏我們不討論他們之間的差異,感興趣的同學可以自行研究,我們主要聚焦於常見的RBAC0模型上。
如下圖就是一個經典RBAC0模型的數據庫設計。
在RBAC模型下,系統只會驗證用户A是否屬於角色RoleX,而不會判斷用户A是否能訪問只屬於用户B的數據DataB。這種問題我們稱之為“水平權限管理問題”。
數據權限
列表數據權限,主要通過數據權限控制行數據,讓不同的人有不同的查看數據規則;要實現數據權限,最重要的是需要抽象出數據規則。
數據規則
比如我們系統的商機數據,需要從下面幾個維度來控制數據訪問權限。
- 銷售人員只能看自己的數據;
- 各大區的銷售經理只能看各區域的數據(安徽大區的銷售經理看安徽區域的商機數據),同理也適用於某BG分管領導只能看所在BG的商機數據;
- 財務人員只能看金額小於一萬的數據。
上面的這些維度就是數據規則。
這樣數據規則的幾個重點要素我們也明晰了,就是規則字段,規則表達式,規則值,上面三個場景對應的規則分別如下:
- 規則字段:創建人,規則表達式: = ,規則值:當前登錄人
- 規則字段:所屬大區,規則表達式: = ,規則值:安徽大區
- 規則字段:銷售金額,規則表達式: < ,規則值:10000
規則字段配置説明:
條件表達式:大於/大於等於/小於/小於等於/等於/包含/模糊/不等於
規則值:指定值 ( 固定值/系統上下文變量 )
關聯資源、用户
光有數據規則是不夠的,我們還需要把數據規則跟資源和用户進行綁定。
數據規則與資源的綁定很簡單,我們只需要建立一箇中間表即可,如下圖所示:
這樣資源就可以關聯上了數據規則。
在應用設計上我們需要一個單獨的數據規則管理功能,方便我們錄入數據規則,然後在資源管理頁面(比如商機列表)上就可以選擇內置的數據規則進行資源與規則的綁定。
那麼如何讓不同的用户擁有不同的數據規則呢?
在RBAC模型中,用户是通過授予不同的角色來進行資源的管理,同理我們可以讓角色在授予權限的時候關聯上數據規則,這樣最終在系統上就體現為不同的用户擁有不同的數據規則。
有點拗口,我們還是按上面的例子來説。
銷售人員、大區銷售經理、財務人員屬於不同的角色,他們都擁有商機列表這個資源權限,但是在給這些角色綁定商機列表資源權限時我們可以勾選對應的數據規則(上面已經實現資源與數據規則的綁定)。體現在數據庫設計中我們可以在角色資源對應關係表 Role_Permission
中添加一個字段用於存儲關聯的數據規則,如果有多個數據規則可以使用分隔符分割。
最終RBAC模型演變成如下所示的模型:
按照上面的設計我們需要區分各個大區管理的數據權限則需要建立不同的大區角色,如安徽大區銷售經理、上海大區銷售經理,然後分別給角色勾選對應的數據規則。這裏就類似於RBAC1中的角色繼承的概念了。
這樣我們就基本實現了RBAC與數據規則的綁定,但是我們還有個問題就是如何在系統中落地。
這裏我們就要藉助大名鼎鼎的AOP來實現了,這篇文章只講原理不講實現,所以我們只順帶提一下實現方案。
- 自定義一個數據權限的註解,比如叫
PermissionData
- 在對應的資源請求方法,比如商機列表上添加自定義註解
@PermissionData
- 利用AOP抓取到用户對應角色的所有數據規則並進行SQL拼接,最終在SQL層面實現數據過濾。
繼續優化
在上面的設計中我們通過給不同角色綁定不同數據規則實現了數據權限,但是考慮下面一種場景:某角色需要看到的數據範圍為 “所屬大區為安徽大區且事業部為消費者事業部的商機數據”,在這種場景裏按照我們之前的設計需要建立兩個數據規則:
- 所屬大區 = 安徽大區
- 所屬事業部 = 消費者事業部
然後再建立2個不同的角色,分別授予不同的數據規則,如果這樣的場景比較多的話很容易出現角色爆炸的情況,所有我們這裏再抽取出 數據規則組 的概念。
一個數據規則組有多個數據規則,數據規則之間通過 AND 進行連接,放一張應用設計圖:
體現在數據庫設計中就變成了如下所示:
小結
通過上面8張表的設計我們實現了RBAC模型與數據權限的結合,當然這裏還有繼續優化的空間。比如這裏的規則字段和規則值我們可以抽取出對應的字典表,讓數據規則表去關聯這些字典字段,這樣在應用層配置數據規則的時候就不需要管理員手動填寫而是從字典項中去選擇了,減少了數據規則配置出錯的概率。
數據權限是一個實現相對比較複雜的功能,這裏我們選擇的是在RBAC模型基礎上進行擴展,如果你有更好的解決方案歡迎留言告訴我。
這篇文章 我們將通過代碼的角度來實現這樣一個數據權限。
- 數據權限就該這麼實現(設計篇)
- 數據權限就該這麼實現(實現篇)
- 給你一段SQL,你會如何優化?
- 當我把ChatGPT機器人拉到微信羣裏,羣友都玩瘋了!!
- SpringBoot 如何保證接口安全?老鳥們都是這麼玩的!
- 掌握系統思維,你就可以既勤奮努力又輕鬆愉快。
- SpringBoot自定義註解 AOP 防止重複提交(建議收藏)
- 面試官:應用上線後Cpu使用率飆升如何排查?
- SpringBoot中實現業務校驗,這種方式才叫優雅!
- SpringCloud Gateway 收集輸入輸出日誌
- 震驚,Spring官方推薦的@Transational還能導致生產事故?
- 為什麼要在MVC三層架構上再加一層Manager層?
- SpringBoot 如何生成接口文檔,老鳥們都這麼玩的!
- SpringBoot 如何進行限流?老鳥們都這麼玩的!
- SpringBoot 生成接口文檔,我用smart-doc,一款比Swagger更nice的工具!
- SpringBoot 如何進行對象複製,老鳥們都這麼玩的!
- 3天,我把MySQL索引、鎖、事務、分庫分表擼乾淨了!
- 字節全面對外開放中台能力!中台,又靈了?
- 基於 Kubernetes 的微服務項目設計與實現
- 老闆要我開發一個簡單的工作流引擎