轉自:http://www.cnblogs.com/kudy/archive/2011/11/10/2243810.html
前天已發過文章分享了剛完成的一個主數據系統,受到了不少朋友的關注,這篇文章主要是對主數據權限設計方案的講解,希望對大家有所幫助。源碼下載與運行說明請查看 分享一個通用強大的主數據管理系統(架構設計講解及源碼下載)
權限管理一般為分授權、驗權兩大塊,另外還有驗權測試,這是在系統測試階段要完成的工作。這里重點要講的是授權,驗權會講一部分。
一、主要數據表設計

這是權限分組表,設計它是為了在管理權限時更加清晰,沒其它特別的意義。

這是權限項表,這個表是重點,其中:
Code是對應系統中的權限碼(例如刪除用戶:delete_user),最終驗權的時候是權限這個權限碼來獲取權限值的。
DisplayStyle是權限項的顯示樣式,除了CheckBox是簡單true/false權限外,TextBox、DropDownList、TreeView這三種都是自己定義數據型權限,也是難點,更是本設計方案的特色,當然還可以擴展其它類型的權限。
JsonDataUrl是支持遠程權限值的初始化,JsonDataConst是支持靜態權限值的初始化,Json數據格式如下:

下面看看添加權限項的界面:

然后看看授權的界面:


這是角色表,每個系統都有自己的多個角色,每個角色都有自己的權限,其中PermissionJsonData就是用於保存權限的。

這是用戶個人的永久權限表,其中PermissionJsonData就是用於保存權限的。

這是用戶個人的臨時權限表,其中PermissionJsonData就是用於保存權限的,BeginDate和EndDate保存權限的有效日期。

這個表是用於保存用戶與角色的關系的,一個用戶可以擁有一個或多個角色。
二、受權的代碼實現

首先,我們需要按需求來定義合理的數據模型(主要給系統的表示層使用的),其中DbModels里放的是和數據表對應的數據模型,ExtendedModels里放的是特別需求擴展的數據模型,JsonModels里放的是Json數據序列化需要的數據模型。其中PermissionDropDownListOption是為DropDownList類型權限設計的,PermissionTreeViewNode是為TreeView類型權限設計的,代碼如下:
 
         PermissionDropDownListOption 
        
 
         PermissionTreeViewNode 
        

寫到這,大家先看一下授權的頁面,初始化控件和保存權限都算是一個難點,在顯示權限控件方面,其實只要獲取相應系統的所有權限項,根據類型來輸出html就行了,難的是DropDownList和TreeView控件,下面兩個方法是返回它們所需的Json數據:
///<summary>
/// 獲取樹視圖Json數據
///</summary>
[Action]
public void GetTreeViewPermissionJsonData(Guid systemId, Guid permissionItemId, string[] checkedIds)
{
PermissionItemModel permissionItem = PermissionItemService.GetById(permissionItemId);
// 轉為對象
PermissionTreeViewJsonData nodes = PermissionUtils.ParsePermissionControlJsonData<PermissionTreeViewJsonData>(this, systemId, permissionItem);
// 初始已選數據
PermissionUtils.InitTreeViewCheckedNodes(nodes, checkedIds);
JsonResult(nodes);
}
///<summary>
/// 獲取下拉框Json數據
///</summary>
[Action]
public void GetDropDownListPermissionJsonData(Guid systemId, Guid permissionItemId, string selectedValue)
{
PermissionItemModel permissionItem = PermissionItemService.GetById(permissionItemId);
// 先轉為對象
PermissionDropDownListJsonData options = PermissionUtils.ParsePermissionControlJsonData<PermissionDropDownListJsonData>(this, systemId, permissionItem);
// 初始已選數據
PermissionUtils.InitDropDownListSelectedOptions(options, selectedValue);
JsonResult(options);
}
重點工作都交給了PermissionUtils助手類來處理了,請看下面的代碼
 
          public static class PermissionUtils 
        
顯示控件處理完了,那保存權限值呢?獲取權限值的實現也放在PermissionUtils助手類里了,第一個方法GetPostedPermissionValues就是獲取提交的權限值。

三、驗權的代碼實現
每個用戶有多個角色,又有永久和臨時權限,那總要處理權限的合理繼承吧,本方案是這樣處理的:
1. 單選框 與 樹視圖 類型,在 角色權限、永久權限、臨時權限(有效時期內) 中任何已勾選的權限都會一直會繼承下去;
2. 文本框 與 下拉框 類型,是按 臨時權限 -〉永久權限 -〉角色權限(按排序的順序) 的順序,前者的權限為空或沒有選擇時才會繼承后者的權限值;
這些處理都在用戶登錄成功的時候處理的,並保存權限值到一個字典里,實現代碼在MDMS.UserApiModule項目中的UserApiService類:
 
         合並用戶權限 
        
要驗證權限,那首先要做的就是獲取權限值,在MDMS.UserApiModule項目中的ServiceContextBase類中實現所有類型的權限值獲取方法,所以子系統只要繼承這個類,就可以輕松的進行權限的驗證了,請看獲取權限值的方法實現:
 
         Permission Services 
        另外值得說的是,GetTreeViewPermissionValue方法有個Func<List<T>, List<T>> rectifyValues參數,它的作用是,如果在授權時勾選了某個根節點,那表示此根節點下的所有權限都是有的,包括以后在該根節點新加的子節點,所以需要額外根據根節點獲取所有的子節點,以確保獲取的權限是完整的。
在主數據系統設計中,主數據系統也被當成自己的一個子系統來處理了,下面看看主數據頁面基類是怎么獲取權限的?
 
         驗證權限 
        
有了上面的頁面基類,最后的權限驗證就變得簡潔方便了

 
寫到這就算結束了,設計中的內容比較多,不好處處仔細的解說。本方案中,用json來保存權限使實現變得簡單了很多,而且是采用key/value的字典格式,所以子系統在以后需要新增新的權限項或刪除權限項,都不會影響到用戶的權限(意思是不用解決權限版本問題,隨意添加刪除權限都可以正常動作),時間問題只能以這種方式來講解了,需要深入了解本方案設計的朋友請下載整個系統的源碼來看,如果本文對你有幫助,請點擊推薦以示支持,謝謝。
在線demo: http://mdms.kudystudio.com/
用戶/密碼:test1/test1 test2/test2 (注:同一用戶在另一瀏覽器登錄,另一用戶在session失效后會被逼下線)

