組織架構(gòu)
1.需求點(diǎn)
- 查詢某個(gè)組織下面的所有用戶(包括所有下級(jí)組織)
- 查詢某個(gè)組織下面的所有下級(jí)組織
- 查詢用戶所在的組織
- 獲取整個(gè)組織結(jié)構(gòu),方便生成樹形數(shù)據(jù)結(jié)構(gòu)
2.組織表
相關(guān)的必要字段如下:
- id,主鍵ID
- pid,父級(jí)組織id
- tree,當(dāng)前節(jié)點(diǎn)的所有父級(jí)組織,假設(shè)當(dāng)前組織的父級(jí)id為2,2的父級(jí)id為1,則tree的值為:1,2
3.用戶表
相關(guān)的必要字段如下:
- department,所在的組織id。
4.相關(guān)SQL
4.1 查詢用戶所在的組織
SELECT * FROM `department` `a`, INNER JOIN user `b` ON `a`.`id` = `b`.`department` WHERE b.id = "用戶ID";
4.2 獲取指定組織下的所有組織
SELECT * FROM `department` WHERE FIND_IN_SET( "組織ID", `tree` )
4.3 查詢組織下面的所有用戶
SELECT * FROM `user` `a` INNER JOIN `department` `b` ON `a`.`department` = `b`.`id` WHERE ( a.department IN (( SELECT id FROM `department` WHERE ( FIND_IN_SET( "組織ID", `tree` ) OR id = "組織ID" ) )) )
角色與權(quán)限
通常情況下有兩種方式可以控制用戶權(quán)限,一種是通過(guò)用戶角色(Role)來(lái)控制權(quán)限,另一種是通過(guò)更細(xì)致的權(quán)限(Operation)來(lái)直接指定某個(gè)用戶可以進(jìn)行哪些行為。
1.角色
不同的角色可以訪問(wèn)的功能集合(可訪問(wèn)的頁(yè)面)不同,創(chuàng)建角色時(shí)設(shè)置角色可訪問(wèn)的頁(yè)面。
前后端分離的模式下,將角色的可訪問(wèn)路由傳遞給前端,由前端動(dòng)態(tài)加載路由。
角色=可訪問(wèn)的頁(yè)面+可操作的權(quán)限 ,按照這個(gè)進(jìn)行設(shè)計(jì),每個(gè)操作和頁(yè)面關(guān)聯(lián)了指定的一些接口
- RBAC0/RBAC1/RBAC2/RBAC3種,基于角色的意思是在系統(tǒng)中創(chuàng)建名為角色的橋梁,將客體的權(quán)限直接與角色進(jìn)行關(guān)聯(lián),訪問(wèn)主體則通過(guò)被賦予的角色來(lái)訪問(wèn)與角色相關(guān)聯(lián)的客體。
- RBAC0:最核心的模型,其主體角色、客體能夠以多對(duì)多的關(guān)系進(jìn)行關(guān)聯(lián):
- RBAC1:引入角色繼承,將角色分為不同等級(jí),且角色間存在上下級(jí)關(guān)系,同時(shí)支持角色間的繼承
- RBAC2:在RBAC0的基礎(chǔ)上約束控制角色,在角色被賦予客體權(quán)限及主體在獲得角色時(shí)應(yīng)遵循強(qiáng)制性約束規(guī)則,包括:互斥角色、角色被賦予主體數(shù)量約束、獲得上級(jí)角色需先獲得下級(jí)角色等
- RBAC3: 覆蓋RBAC0/RBAC1/RBAC2所有功能。
參考:https://blog.csdn.net/weixin_42149145/article/details/112575531
2.動(dòng)態(tài)路由
系統(tǒng)初始化的時(shí)候,只加載一些初始的路由頁(yè)面(比如登錄頁(yè)面),登錄成功后,從后臺(tái)請(qǐng)求對(duì)應(yīng)權(quán)限的路由表,然后通過(guò)router.addRoute動(dòng)態(tài)添加路由。
for (let x of res) {
router.addRoute(x)
}
3.架構(gòu)設(shè)計(jì)
前端可以設(shè)計(jì)如下一些功能,以Vue為例:
- 鑒權(quán)函數(shù),auth
- 鑒權(quán)指令,v-auth
- 鑒權(quán)組件,<v-auth>
后端則按照如下規(guī)則進(jìn)行權(quán)限判斷:
- 角色 -> 獲取可訪問(wèn)的頁(yè)面 -> 獲取頁(yè)面相關(guān)的權(quán)限 -> 獲取權(quán)限關(guān)聯(lián)的后端接口
- 刪除權(quán)限(總表)時(shí),外鍵同步刪除頁(yè)面和權(quán)限的關(guān)聯(lián),外鍵又同步刪除角色和權(quán)限的關(guān)聯(lián),外鍵同步刪除權(quán)限和接口的關(guān)聯(lián)
- 刪除路由(總表)時(shí),外鍵同步刪除權(quán)限,外鍵同步刪除頁(yè)面和權(quán)限的關(guān)聯(lián),外鍵又同步刪除角色和權(quán)限的關(guān)聯(lián),外鍵同步刪除權(quán)限和接口的關(guān)聯(lián)
- 刪除角色和頁(yè)面時(shí),強(qiáng)制存在子元素時(shí)不可刪除(邏輯上限制以及數(shù)據(jù)庫(kù)外鍵限制)
- 父角色刪除一個(gè)可訪問(wèn)的頁(yè)面時(shí),同步刪除所有子角色的頁(yè)面,同時(shí)要?jiǎng)h除整個(gè)角色樹上跟這個(gè)頁(yè)面關(guān)聯(lián)的所有權(quán)限
- 父角色刪除一個(gè)權(quán)限時(shí),同步刪除所有角色樹上子角色的權(quán)限。
- 新增頁(yè)面或者權(quán)限時(shí),同步給系統(tǒng)管理員新增該頁(yè)面和權(quán)限。
4.問(wèn)題總結(jié)
- 展示子角色的可選頁(yè)面時(shí),應(yīng)該拉取它的父角色可訪問(wèn)頁(yè)面
- 用戶不可以修改自己的角色。
- 但是可以獲取不包括自己角色的角色樹
- 子角色新增、修改的頁(yè)面,必須在父角色的頁(yè)面集合內(nèi)。
- 路由修改父級(jí)路由時(shí),不能選擇自己
- 刪除,新增,修改角色時(shí),都需要判斷用戶有沒(méi)有權(quán)限
- 刪除,新增,修改指定角色的頁(yè)面時(shí),都需要判斷權(quán)限
- 獲取權(quán)限列表,要綜合父角色的已有權(quán)限和當(dāng)前角色擁有的頁(yè)面
- 刪除角色時(shí),判斷有沒(méi)有該角色的用戶,有的話不允許刪除
5.組織和用戶
- 移動(dòng)一個(gè)組織,要修改它下面所有組織的組織樹
- 移動(dòng)一個(gè)頁(yè)面,要修改它下面所有頁(yè)面的頁(yè)面樹
- 修改組織和頁(yè)面的父級(jí)時(shí),不能選擇自身或下級(jí)組織、頁(yè)面
- 上級(jí)用戶修改、刪除下級(jí)用戶時(shí),要先從組織和角色兩方面去判斷
- 刪除用戶時(shí),假如用戶賬號(hào)內(nèi)還有客戶,則不允許刪除。
- 刪除組織時(shí),組織內(nèi)還有用戶,也不允許刪除
- 刪除組織時(shí),如果有子組織則不允許刪除
6.權(quán)限判斷
設(shè)計(jì)到權(quán)限判斷的操作:新增、修改、刪除、查詢
判斷用戶對(duì)一個(gè)客戶是否擁有權(quán)限
- 是不是自己的客戶
- 是不是自己所在組織或下級(jí)組織的用戶的客戶
- 有沒(méi)有處理下級(jí)用戶的客戶的權(quán)限
判斷用戶有沒(méi)有操作另一個(gè)用戶的權(quán)限
- 是不是自己所在組織或下級(jí)組織的用戶
- 有沒(méi)有處理下級(jí)組織用戶的權(quán)限
判斷用戶有沒(méi)有操作一個(gè)組織的權(quán)限
- 是不是自己所在組織或下級(jí)組織
- 有沒(méi)有操作下級(jí)組織的權(quán)限
角色的上下級(jí)關(guān)系,只能用于用戶添加和用戶角色修改的范圍限制,單純的角色上下級(jí)關(guān)系不能作為權(quán)限判斷的條件
系統(tǒng)分庫(kù)模式
1.思考點(diǎn)
多公司分庫(kù)模式下,多出來(lái)的一些思考點(diǎn):
主表(公共表):
- 公司表
- 路由表
- 權(quán)限表
公司表:
- 角色與權(quán)限關(guān)聯(lián)
- 角色與路由的關(guān)聯(lián)
適配修改:
- 新增一個(gè)權(quán)限,是否是系統(tǒng)管理員。
- 修改角色與權(quán)限、角色與路由的關(guān)聯(lián),通過(guò)跨庫(kù)外鍵去約束。
- 新增權(quán)限時(shí),可選是否應(yīng)用到所有公司管理員的角色上。
- 操作角色權(quán)限、組織架構(gòu)判斷操作的是哪個(gè)公司
2.跨公司操作
管理員跨公司操作時(shí),需要處理的細(xì)節(jié):
- 角色切換,如何平滑處理不同公司的角色權(quán)限的問(wèn)題?
- 組織切換,如果平滑處理不同公司組織架構(gòu)的問(wèn)題?
- 公司切換,切換公司之后,需要判斷是否具有權(quán)限以及切換對(duì)應(yīng)的連接池
總結(jié):切換公司之后,權(quán)限判斷走本身所在公司的角色,部門修改為所選公司的根節(jié)點(diǎn),角色修改為根角色(權(quán)限不同步改變)
- 根據(jù)中間件執(zhí)行的先后順序,接口權(quán)限判斷的中間件會(huì)先于公司切換的中間件運(yùn)行,在接口權(quán)限判斷的階段就緩存好用戶權(quán)限,之后不再重新初始化。
問(wèn)題記錄
1.客戶查詢
查詢當(dāng)前用戶的下級(jí)用戶的所有客戶的訂單數(shù)據(jù),查詢出權(quán)限范圍內(nèi)的去重后的客戶ID集合,然后再去通過(guò)in判斷客戶是否在這個(gè)集合內(nèi)。客戶數(shù)量越來(lái)越多時(shí),如何處理?
客戶的更新頻率不會(huì)很高,通過(guò)建表,緩存指定用戶的客戶ID,并實(shí)時(shí)更新,然后將這個(gè)表用于IN查詢