1. 程式人生 > >資料許可權設計(轉載)

資料許可權設計(轉載)

https://www.cnblogs.com/gcczhongduan/p/4822814.html
https://www.cnblogs.com/leoxie2011/archive/2012/03/18/2400367.html

一、前言

幾乎在任何一個系統中,都離不開許可權的設計,許可權設計 = 功能許可權 + 資料許可權,而功能許可權,在業界常常是基於RBAC(Role-Based Access Control)的一套方案。而資料許可權,則根據不同的業務場景,則許可權卻不盡相同,應該根據具體的場景巧妙設計; 且必須在專案開始時進行設計,不像功能許可權一樣,在專案結束的時候在追加。

:更細還可以加入欄位許可權


1.1 許可權型別

【功能許可權】:能做什麼的問題,如增加產品。
【資料許可權】:能看到哪些資料的問題,如檢視本人的所有訂單。
【欄位許可權】:能看到哪些資訊的問題,如供應商賬戶,看不到角色、 部門等資訊。


二、資料許可權設計

2.1 應用場景

  • 訂單,可以由本人檢視
  • 銷售單,可以由本人或上級領導檢視
  • 銷售單,銷售人員可以檢視自己的,銷售經理只檢視 銷售金額大於100,000的。

2.2 資料許可權設計分析

資料許可權跟功能許可權有非常大的不同,顆粒度非常小。貫穿於整個專案的開發週期中,無法像功能許可權一樣在專案要結尾的時候追加。資料許可權做不到元件級別,必須在專案設計階段就已經規劃好。之前看網上相同有人想基於SPRING

切面的原理去實現資料許可權,這樣就能夠做到了低侵入、低耦合,想法非常好。但是現實非常骨感,這樣做使整個應用系統效率大減折扣,相同對資料許可權的控制策略也非常不靈活


2.3 SQL語句可擴充套件,資料許可權設計分析

資料許可權往往作為功能許可權的高階行為。能夠從資料物件的幅度方面進行控制。比方使用者僅僅能看自己的訂單、普通會員看不到某資料物件的高階屬性(欄位)等等。顆粒度這麼細的情況下對結果集處理顯然是不可能了,這時僅僅能介入到SQL語句中,此時又不想在開發階段讓開發者過多的考慮資料許可權的問題,這個時候就需要將sql 和資料許可權策略分開。再呼叫介面的時候,進行資料許可權介面的拼接。這樣也算做到的程式碼的低侵入。


2.4 SQL語句高效解析處理

資料許可權模組的核心之中的一個就有SQL語句的高效解析處理,SQL處理指依據當前登入人資訊及資料許可權策略生成一個帶有資料許可權處理結果的SQL語句。所以這裡對SQL語句的解析處理必需要求精確、準確。在開發階段由開發者把SQL寫入到配置檔案裡,在執行階段由資料許可權取得該SQL進行分析處理(加上資料許可權),這樣就完畢了SQL的組裝處理。


2.5 資料許可權策略設計

最核心的地方就是資料許可權策略的設計了,這裡先引入幾個概念:

  • 資源:資料許可權的控制物件,業務系統中的各種資源。比方訂單單據、銷售單等
  • 主體:使用者、部門、角色等
  • 條件規則:用於檢索資料的條件定義
  • 資料規則:用於【資料許可權】的條件規則

簡單例子:包含了資源,主體,規則。
這裡寫圖片描述

規則應用中:銷售員只能檢視到自己的銷售訂單。


2.6 思考兩個問題:

第一,如何配置
第二,如何拼接sql語句

2.6.1 應用示例

  • 訂單,可以由本人檢視
  • 銷售單,可以由本人或上級領導檢視
  • 銷售單,銷售人員可以檢視自己的,銷售經理只檢視 銷售金額大於100,000的。
    我們能想到直接的方法,在訪問資料的入口加入SQL Where條件來實現,組織sql語句
where UserID = {CurrentUserID}
where UserID = {CurrentUserID}  or {CurrentUserID} in (領導)
where UserID = {CurrentUserID}  or ({CurrentUserID} in (銷售經理)  and 銷售金額 > 100000)

這些一個一個的條件,簡單理解為一個【資料規則】。


不同的人應該對應不同的規則,那麼也可以理解為,一個使用者對應不同的角色,每一個角色有不一樣的【資料規則】,那麼設計就變成
【資源】 - 【主體】 - 【資料規則】

根據提供者的不同,準備不同的許可權應對策略。


2.6.2 資源 - 規則

使用JSON 格式,將資源和規則得到應用。

{
	"rules": [{
		"field": "CustomerID",
		"op": "like",
		"value": "AN",
		"type": "string"
	}],
	"op": "and"
}

上面的格式再考慮安全性的時候,不夠高,推薦下面這種方式:

{
	"rules": [{
			"field": "OrderDate",
			"op": "less",
			"value": "2012-01-01"
		},
		{
			"field": "CustomerID",
			"op": "equal",
			"value": "VINET"
		}
	],
	"op": "and"
}

(過濾規則分為三個部分:【分組】、【規則】(欄位、值、操作符)、【操作符】(and or),而自身就是一個分組。)
規則描述:

查詢顧客VINET所有訂單時間小於2011-01-01的單據


這樣的資料是安全的,而且是通用的(你甚至可以再加一個OR子查詢)。無論是在前端還是後臺,無論你使用什麼樣的元件,都可以很好地利用。

通用後臺的翻譯,就可以生成這樣SQL的引數:

Text:
([OrderDate] < @p1 and [CustomerID] = @p2)
Parameters:
p1:2012-01-01
p2:VINET

2.6 欄位許可權

如果說資料許可權是對功能許可權在縱向的擴充套件,那麼欄位許可權就是在橫向的擴充套件。可以禁止指定使用者/角色 對某些欄位的訪問
這裡寫圖片描述