資料許可權設計——基於EntityFramework的資料許可權設計方案:一種設計思路
前言:“我們有一個訂單列表,希望能夠根據當前登陸的不同使用者看到不同型別的訂單資料”、“我們希望不同的使用者能看到不同時間段的掃描報表資料”、“我們系統需要不同使用者檢視不同的生產報表列”。諸如此類,最近經常收到專案上面的客戶提出的這種問題,即所謂的“資料許可權”,經過開會討論決定:在目前的開發框架上面搭建一套通用的資料許可權功能。
一、大話許可權模組
有了上面的引言,自然而然就引出了今天需要和大家討論的話題——資料許可權。作為開發人員,我們肯定知道,一般的系統都離不開許可權模組,它是支撐整個系統執行的基礎模組。而根據專案型別和需求的不同,許可權模組的設計更是大相徑庭。但不管怎麼變,許可權模組從大的方面來說,可以分為兩種大的型別:功能許可權
- 功能許可權:主要控制不同的資源主體(使用者、角色、組織等)有操作不同的資源的許可權。比如常見的不同的角色能訪問不同的頁面(選單許可權),以及具有操作同一頁面的不同功能(按鈕許可權)等等,都資料功能許可權的範疇,這種設計相對比較簡單,也比較為大多數系統所通用。當然網上資料、設計思路也可以找到很多。
- 資料許可權:主要控制不同的資源主體(使用者、角色、組織等)有檢視不同的資料資訊的許可權,一般來說,資料許可權又分為資料行許可權和資料列許可權,通過字面意思不難理解這兩者的區別,比如上文“我們有一個訂單列表,希望能夠根據當前登陸的不同使用者看到不同型別的訂單資料” 這就是一個典型的資料行許可權,而“我們系統需要不同使用者檢視不同的生產報表列”這就是資料列許可權的範疇。由於資料許可權和系統的業務邏輯關係非常密切,所以不同的系統設計差異性會非常大。從另一方面來說,由於資料許可權和業務邏輯關聯性非常強,如果系統的業務邏輯非常複雜,資料許可權設計起來也會相對複雜,所以關於資料許可權的設計一直沒有一種相對通用和使用簡單的設計方案。
如果你動手去設計資料許可權,當你去各大平臺、百度、谷歌查詢設計思路的時候,你會發現很難找到有用的資料,很多設計思路侷限性非常大。其實原因很簡單:資料許可權的設計和他人系統關係緊密,一般不太容易拿到你的專案上面直接使用。
當然也有另外部分人說“資料許可權並不能作為許可權模組去設計”,比如博主看到這樣一條評論
從一定程度上來說,這樣理解也不為過,如果你覺得你的系統靈活性和配置性不需要那麼高,把資料許可權的規則在程式碼裡面寫死又何妨,博主所在公司的另外一個部門就是這麼幹的,除了編碼量大一點,其實也沒什麼太大的問題!其實博主說這麼多無非是想表達一個觀點:沒有絕對通用的資料許可權設計思路,關鍵看合不合你用!當然本文的設計思路也是一樣,不強制要求,不提通用。設計思路供你參考!
二、一種設計思路
關於許可權設計的雜談就告一段落,凡是點到即止,再說了多了就說爛了。到目前為止,博主找到的一篇寫得相對比較好的文章 通用許可權管理設計 之 資料許可權。這位博主是用sql去實現的,如果是把這個運用到EF裡面的話,考慮到EF複雜的導航屬性,會有一些問題。接下來說說博主這邊想到的設計思路。
先說說博主所在專案的情況,和資料打交道的部分採用EntityFramework+Repository的傳統模式去實現的,整個專案從上到下,就是一種典型的"偽DDD",什麼是”偽DDD“?這裡不做過多說明,使用過DDD的同仁應該很清楚。下面是設計思路流程圖:
第一步:配置資料規則
第二步:頁面使用資料規則
以上是一個大致的思路圖,總的來說,要實現基於EF的資料許可權設計,主要分為兩大步驟
1、配置資料規則
配置資料規則這裡有三個大的方面:功能模組、資料資源、角色
- 功能模組:為什麼這裡要加上功能模組的約束?是因為博主覺得我們某一個頁面在查詢資料的時候,會有一個查詢的範圍,比如訂單查詢頁面肯定只能查詢和訂單有關聯的實體功能,而不可能查詢和它沒有任何關聯的業務。加這個約束更大的意義在於我們動態的構造Lambda去查詢實體的時候不會產生”找不到相關聯的實體“之類的錯誤。
- 資料資源:具體對哪種資料資源做資料許可權,比如訂單的狀態不等於取消狀態、訂單的下單時間小於當前月份等等。
- 角色:資料資源的主體,還可以是使用者、部門、組織等等。
這三者配置之後得到的一個結果就是某一類角色的某一個功能模組對哪個資料資源的資料規則是什麼樣的。比如有一條銷售總監的資料規則,配置銷售總監在訂單模組裡面訂單這個實體的訂單型別是銷售訂單的所有資料,這就是針對銷售總監在訂單模組的資料規則。可能最終資料庫儲存得到的資料類似這樣:
RoleId | FunctionCode | Rules |
2 | OrderQuery |
{"rules":[{"field":"Order_Status","operate":"in","value":"[0,1,2]"},{"field":"Order_Type","op":"equal","value":"1"}],"logicoperate":"and"} |
3 | OrderQuery |
{"rules":[{"field":"Order_Status","operate":"in","value":"[0]"},{"field":"Product.Categary.Type","equal":"equal","value":"1"}],"logicoperate":"and"} |
5 | Product |
{"groups":[ {"rules":[{"field":"Order_Status","operate":"in","value":"[0,5,10]"},{"field":"Order_Type","op":"equal","value":"1 "}],"logicoperate":"and"}, {"rules":[{"field":"LineName","operate":"equal","value":"fenzhuangxian"}]} ],"logicoperate":"or"} |
需要特別說明的是:由於EF有導航屬性,這裡的Rules在儲存的時候如果遇到導航屬性,我們的欄位值需要這樣儲存——Product.Categary.Type。因為在我們轉換成為lambda表示式的時候導航屬性會是這樣寫:x=>x.Product.Categary.Type==1。這個我們在後面使用這個規則的時候加以說明。
2、使用資料規則
有了上面的資料規則,接下來就是我們在取資料的時候如何使用了,這裡有一點需要說明的是:我們這裡需要傳兩個引數,一個是模組的名稱,比如上面的OrderQuery、Product等;第二個是當前使用者的角色id,這個可以通過當前登陸使用者的id獲取到角色。
要使用資料規則,之前博主分享過兩篇關於動態Lambda的文章,現在派上用場了。只不過原來只是一些基礎型別轉lambda,現在涉及到了導航屬性,不知道是否可行。博主查閱了一些資料,最終找到了解決方案。
//遍歷得到屬性(包括遍歷導航屬性) public Expression GetProperty(Expression source, ParameterExpression para, string Name) { string[] propertys = Name.Split('.'); if (source == null) { source = Expression.Property(para, typeof(Entity).GetProperty(propertys.First())); } else { source = Expression.Property(source, propertys.First()); } foreach (var item in propertys.Skip(1)) { source = GetProperty(source, para, item); } return source; }
然後測試如下
var oLamadaExtention = new LambdaExpression<Order>(); var left = oLamadaExtention.GetProperty(null, Expression.Parameter(typeof(Order), "x"), "Product.Categary.Type"); var value = Expression.Constant("1", left.Type); //動態轉換型別 var right = Expression.Constant(value, left.Type); Expression expRes = Expression.Equal(left, right);
測試得到的查詢lambda結果為x=>x.Product.Categary.Type=="1",測試成功!
3、補充一點
對於配置資料規則的時候還有一點比較麻煩的是,如果如何知道哪個功能模組使用哪些實體?不可能直接讓使用者去寫Product.Categary.Type這些複雜的功能吧,如果是這樣,談何體驗。那麼只有使用另外一種解決思路了——反射EF實體。
反射EF實體的時候如果是導航屬性,還得繼續反射導航屬性的實體,這樣一層一層反射下去,最終確實是可以得到形如Product.Categary.Type這個的結構體,但介面如何展現還有待思考。比如思路如下:
三、總結
以上只是一個設計思路,理論上來說是可以實現的,如有不足,歡迎斧正,謝謝。如果思路沒有問題,後續博主會抽時間將這種設計的實現過程展現出來供大家參考,歡迎關注。其中的難點有兩個:
1、逐級反射EF的導航屬性,以及這個過程如何展現。是通過特性標記,還是開發人員配置;
2、動態Expression在構造Lambda的時候和配置資料的相容性問題,比如資料型別的相容性有點難控制。
歡迎各位轉載,但是未經作者本人同意,轉載文章之後必須在文章頁面明顯位置給出作者和原文連線,否則保留追究法律責任的權利
相關推薦
資料許可權設計——基於EntityFramework的資料許可權設計方案:一種設計思路
前言:“我們有一個訂單列表,希望能夠根據當前登陸的不同使用者看到不同型別的訂單資料”、“我們希望不同的使用者能看到不同時間段的掃描報表資料”、“我們系統需要不同使用者檢視不同的生產報表列”。諸如此類,最近經常收到專案上面的客戶提出的這種問題,即所謂的“資料許可權”,經過開會討論決定:在目前的開發框架上面搭建
資料倉庫中,緩慢變化維的一種設計方案
資料倉庫中,緩慢漸變維度是一種經常使用到的方案。 “漸變”,即為逐漸變化的維度,因為日常應用中,維度屬性是隨時可能發生變化的,而BI統計時,又可能是需要歷史某個時間點的維度屬性值。所以這種情況下,就需要我們記錄下這個變化資訊,於是漸變維度就出現了。 “緩慢”兩個字,也是需要
[大資料專案]-0011-基於大資料技術推薦系統演算法案例實戰視訊教
2018最新最全大資料技術、專案視訊。整套視訊,非那種淘寶雜七雜八網上能免費找到拼湊的亂八七糟的幾年前的不成體系浪費咱們寶貴時間的垃圾,詳細內容如下,視訊高清不加密,需要的聯絡QQ:3164282908(加Q註明51CTO)。 [大資料專案]-0010-基於大資料技術
[大資料專案]-0017-基於大資料體系構建資料倉庫
2018最新最全大資料技術、專案視訊。整套視訊,非那種淘寶雜七雜八網上能免費找到拼湊的亂八七糟的幾年前的不成體系浪費咱們寶貴時間的垃圾,詳細內容如下,視訊高清不加密,需要的聯絡QQ:3164282908(加Q註明51CTO)。 課程介紹 本課程系統的、全面的、深入的講解了,基於大資
藍芽控制arduino的安卓軟體(基於app inventor2 )(之一:andriod軟體設計篇)
藍芽控制arduino的安卓軟體(基於app inventor ) 最近在無線電雜誌上看到關於app inventor 的內容,趕腳很厲害,從圖書館回來後就開始嘗試,發現真的不錯。因為之前在用arduino,所以我想能能不能用app inventor寫軟體通過WIFI
【問底】伍藝:一種基於Rsync演算法的資料庫備份方案設計
根據容災備份系統對備份類別的要求程度,資料庫備份系統可以分為資料級備份和應用級備份。資料備份是指建立一個異地的資料備份系統,該系統是對原本地系統關鍵應用資料實時複製。當出現故障時,可由異地資料系統迅速恢復本地資料從而保證業務的連續性。應用級備份比資料備份層次更高,即在異地建
【大資料架構】基於大資料的消費信貸平臺
金融的核心是風控,而好的風控依託於資料。作為依託於大資料驅動的信用消費金融平臺的量化派,為了給信
基於SQLSERVER實現:含分隔符字串資料轉換為多值IN列表的一種解決思路
基於SQLSERVER實現:含分隔符字串資料轉換為多值IN列表場景描述:資料表有一個字串,如 '3,1,2'你希望在where 子句中使用上述字串,但是下面的SQL會由於EMPNO列是數值欄位而執行失敗。select * from emp where empno in ('3,1,2')原因是EMPNO是數
轉:23種設計模式的應用場景
橋模式 man 16px pop 表示 black strong art bstr 設計模式主要分三個類型:創建型、結構型和行為型。 其中創建型有: 一、Singleton,單例模式:保證一個類只有一個實例,並提供一個訪問它的全局訪問點 ;
【python+selenium搭建自動化框架】框架設計中的一種設計思想--POM
例如 了解 思想 對象 業務 class a 如果 對象模型 模型 POM,中文:頁面對象模型,POM是近幾年非常流行的自動化測試模型,或者思想,POM不是框架,是解決問題的一種思想。 采用POM目的:為了解決前端中UI變化頻繁,從而造成測試自動化腳本維護的成本越來越大 P
《UML面向物件建模與設計》第2章——建模是一種設計技術
雖然寫這個部落格主要目的是為了給我自己做一個思路記憶錄,但是如果你恰好點了進來,那麼先對你說一聲歡迎。我並不是什麼大觸,只是一個菜菜的學生,如果您發現了什麼錯誤或者您對於某些地方有更好的意見,非常歡迎您的斧正! 2.1建模 ·在構建物理實體之前先測試 ·與客戶交流 ·
Citco推出CitcoConnect:一種針對安全資料共享和數字投資的全新獨立解決方案
紐約--(美國商業資訊)--金融服務行業全球領先的服務提供商Citco Group of Companies (“Citco”)今天宣佈推出CitcoConnect,這一全新的數字解決方案用於自動化和簡化對潛在投資者的管理流程,包括一個對另類基金進行初始投資的線上工具。 該
php 十一種設計模式
&nbs
Android多執行緒操作sqlite資料庫連線池框架的一種設計思路
我們在Android應用程式開發當中經常會用到資料庫,一般在有兩種主要開發思路。 第一種:每次需要對資料庫操作的時候建立連線,操作完成後,馬上關閉連線。 這個方式一般用於不怎麼頻繁操作資料庫的情況,用完後馬上關閉達到節省系統資源的目的。 第二種:應用程式一
Java技術_每天掌握一種設計模式(002)_使用場景及簡單例項(建立型:單例模式)
1.模式描述 一個類有且僅有一個例項,並且自行例項化並向整個系統提供。 2.模式作用 保證某個類在系統中只有一個例項物件,對於特殊需求來說非常必要。 限制了例項個數有利於GC的回收。
Java技術_每天掌握一種設計模式(006)_使用場景及簡單例項(建立型:原型模式)
1.模式描述 用原型例項指定建立物件的種類,並且通過拷貝來建立新的物件。 2.模式作用 可以一定程度上解耦,消費者和物件的構造過程隔離開,物件如何構造與消費者完全無關。 可以一定程度提升效率,複雜物件的構造往往需要較長的時間(中間可能會進行復雜運算或者資料庫
Java技術_每天掌握一種設計模式(003)_使用場景及簡單例項(建立型:工廠方法)
1.模式描述 提供一個用於建立物件的介面(工廠介面),讓其實現類(工廠實現類)決定例項化哪一個類(產品類),並且由該實現類建立對應類的例項。 2.模式作用 可以一定程度上解耦,消費者和
架構設計:一種遠端呼叫服務的設計構思(zookeeper的一種應用實踐)
在深入學習zookeeper我想先給大家介紹一個和zookeeper相關的應用例項,我把這個例項命名為遠端呼叫服務。通過對這種應用例項的描述,我們會對zookeeper應用場景會有深入的瞭解。 遠端呼叫是系統與系統之間的通訊機制,它的另一種理解就是程序間的通訊。做分散式
Disruptor:一種高效能的、在併發執行緒間資料交換領域用於替換有界限佇列的方案
Disruptor:一種高效能的、在併發執行緒間資料交換領域用於替換有界限佇列的方案 Martin Thompson Dave Farley Micheal Barker Patricia Gee Andrew Stewart 1 摘要 LMAX公司被建立去構建一種高效
軟體架構設計原則和模式(上):分層架構設計
緒論 本文打算探討一下軟體架構設計的一些設計原則與經過實踐驗證的設計模式。這些軟體架構設計的原則和模式已經有幾十年的歷史了。 分層架構設計 軟體,應該根據其職能分成多個層次。分層架構設計思想,有很多成功的例子。如網路設計上,OSI七層網路模型,就把網路