轉(zhuǎn)自:http://www.cnblogs.com/kudy/archive/2011/11/10/2243810.html
前天已發(fā)過文章分享了剛完成的一個(gè)主數(shù)據(jù)系統(tǒng),受到了不少朋友的關(guān)注,這篇文章主要是對(duì)主數(shù)據(jù)權(quán)限設(shè)計(jì)方案的講解,希望對(duì)大家有所幫助。源碼下載與運(yùn)行說明請查看 分享一個(gè)通用強(qiáng)大的主數(shù)據(jù)管理系統(tǒng)(架構(gòu)設(shè)計(jì)講解及源碼下載)
權(quán)限管理一般為分授權(quán)、驗(yàn)權(quán)兩大塊,另外還有驗(yàn)權(quán)測試,這是在系統(tǒng)測試階段要完成的工作。這里重點(diǎn)要講的是授權(quán),驗(yàn)權(quán)會(huì)講一部分。
一、主要數(shù)據(jù)表設(shè)計(jì)
這是權(quán)限分組表,設(shè)計(jì)它是為了在管理權(quán)限時(shí)更加清晰,沒其它特別的意義。
這是權(quán)限項(xiàng)表,這個(gè)表是重點(diǎn),其中:
Code是對(duì)應(yīng)系統(tǒng)中的權(quán)限碼(例如刪除用戶:delete_user),最終驗(yàn)權(quán)的時(shí)候是權(quán)限這個(gè)權(quán)限碼來獲取權(quán)限值的。
DisplayStyle是權(quán)限項(xiàng)的顯示樣式,除了CheckBox是簡單true/false權(quán)限外,TextBox、DropDownList、TreeView這三種都是自己定義數(shù)據(jù)型權(quán)限,也是難點(diǎn),更是本設(shè)計(jì)方案的特色,當(dāng)然還可以擴(kuò)展其它類型的權(quán)限。
JsonDataUrl是支持遠(yuǎn)程權(quán)限值的初始化,JsonDataConst是支持靜態(tài)權(quán)限值的初始化,Json數(shù)據(jù)格式如下:
下面看看添加權(quán)限項(xiàng)的界面:
然后看看授權(quán)的界面:
這是角色表,每個(gè)系統(tǒng)都有自己的多個(gè)角色,每個(gè)角色都有自己的權(quán)限,其中PermissionJsonData就是用于保存權(quán)限的。
這是用戶個(gè)人的永久權(quán)限表,其中PermissionJsonData就是用于保存權(quán)限的。
這是用戶個(gè)人的臨時(shí)權(quán)限表,其中PermissionJsonData就是用于保存權(quán)限的,BeginDate和EndDate保存權(quán)限的有效日期。
這個(gè)表是用于保存用戶與角色的關(guān)系的,一個(gè)用戶可以擁有一個(gè)或多個(gè)角色。
二、受權(quán)的代碼實(shí)現(xiàn)
首先,我們需要按需求來定義合理的數(shù)據(jù)模型(主要給系統(tǒng)的表示層使用的),其中DbModels里放的是和數(shù)據(jù)表對(duì)應(yīng)的數(shù)據(jù)模型,ExtendedModels里放的是特別需求擴(kuò)展的數(shù)據(jù)模型,JsonModels里放的是Json數(shù)據(jù)序列化需要的數(shù)據(jù)模型。其中PermissionDropDownListOption是為DropDownList類型權(quán)限設(shè)計(jì)的,PermissionTreeViewNode是為TreeView類型權(quán)限設(shè)計(jì)的,代碼如下:
寫到這,大家先看一下授權(quán)的頁面,初始化控件和保存權(quán)限都算是一個(gè)難點(diǎn),在顯示權(quán)限控件方面,其實(shí)只要獲取相應(yīng)系統(tǒng)的所有權(quán)限項(xiàng),根據(jù)類型來輸出html就行了,難的是DropDownList和TreeView控件,下面兩個(gè)方法是返回它們所需的Json數(shù)據(jù):
///<summary>
/// 獲取樹視圖Json數(shù)據(jù)
///</summary>
[Action]
public void GetTreeViewPermissionJsonData(Guid systemId, Guid permissionItemId, string[] checkedIds)
{
PermissionItemModel permissionItem = PermissionItemService.GetById(permissionItemId);
// 轉(zhuǎn)為對(duì)象
PermissionTreeViewJsonData nodes = PermissionUtils.ParsePermissionControlJsonData<PermissionTreeViewJsonData>(this, systemId, permissionItem);
// 初始已選數(shù)據(jù)
PermissionUtils.InitTreeViewCheckedNodes(nodes, checkedIds);
JsonResult(nodes);
}
///<summary>
/// 獲取下拉框Json數(shù)據(jù)
///</summary>
[Action]
public void GetDropDownListPermissionJsonData(Guid systemId, Guid permissionItemId, string selectedValue)
{
PermissionItemModel permissionItem = PermissionItemService.GetById(permissionItemId);
// 先轉(zhuǎn)為對(duì)象
PermissionDropDownListJsonData options = PermissionUtils.ParsePermissionControlJsonData<PermissionDropDownListJsonData>(this, systemId, permissionItem);
// 初始已選數(shù)據(jù)
PermissionUtils.InitDropDownListSelectedOptions(options, selectedValue);
JsonResult(options);
}
重點(diǎn)工作都交給了PermissionUtils助手類來處理了,請看下面的代碼
顯示控件處理完了,那保存權(quán)限值呢?獲取權(quán)限值的實(shí)現(xiàn)也放在PermissionUtils助手類里了,第一個(gè)方法GetPostedPermissionValues就是獲取提交的權(quán)限值。
三、驗(yàn)權(quán)的代碼實(shí)現(xiàn)
每個(gè)用戶有多個(gè)角色,又有永久和臨時(shí)權(quán)限,那總要處理權(quán)限的合理繼承吧,本方案是這樣處理的:
1. 單選框 與 樹視圖 類型,在 角色權(quán)限、永久權(quán)限、臨時(shí)權(quán)限(有效時(shí)期內(nèi)) 中任何已勾選的權(quán)限都會(huì)一直會(huì)繼承下去;
2. 文本框 與 下拉框 類型,是按 臨時(shí)權(quán)限 -〉永久權(quán)限 -〉角色權(quán)限(按排序的順序) 的順序,前者的權(quán)限為空或沒有選擇時(shí)才會(huì)繼承后者的權(quán)限值;
這些處理都在用戶登錄成功的時(shí)候處理的,并保存權(quán)限值到一個(gè)字典里,實(shí)現(xiàn)代碼在MDMS.UserApiModule項(xiàng)目中的UserApiService類:
要驗(yàn)證權(quán)限,那首先要做的就是獲取權(quán)限值,在MDMS.UserApiModule項(xiàng)目中的ServiceContextBase類中實(shí)現(xiàn)所有類型的權(quán)限值獲取方法,所以子系統(tǒng)只要繼承這個(gè)類,就可以輕松的進(jìn)行權(quán)限的驗(yàn)證了,請看獲取權(quán)限值的方法實(shí)現(xiàn):
另外值得說的是,GetTreeViewPermissionValue方法有個(gè)Func<List<T>, List<T>> rectifyValues參數(shù),它的作用是,如果在授權(quán)時(shí)勾選了某個(gè)根節(jié)點(diǎn),那表示此根節(jié)點(diǎn)下的所有權(quán)限都是有的,包括以后在該根節(jié)點(diǎn)新加的子節(jié)點(diǎn),所以需要額外根據(jù)根節(jié)點(diǎn)獲取所有的子節(jié)點(diǎn),以確保獲取的權(quán)限是完整的。
在主數(shù)據(jù)系統(tǒng)設(shè)計(jì)中,主數(shù)據(jù)系統(tǒng)也被當(dāng)成自己的一個(gè)子系統(tǒng)來處理了,下面看看主數(shù)據(jù)頁面基類是怎么獲取權(quán)限的?
有了上面的頁面基類,最后的權(quán)限驗(yàn)證就變得簡潔方便了
寫到這就算結(jié)束了,設(shè)計(jì)中的內(nèi)容比較多,不好處處仔細(xì)的解說。本方案中,用json來保存權(quán)限使實(shí)現(xiàn)變得簡單了很多,而且是采用key/value的字典格式,所以子系統(tǒng)在以后需要新增新的權(quán)限項(xiàng)或刪除權(quán)限項(xiàng),都不會(huì)影響到用戶的權(quán)限(意思是不用解決權(quán)限版本問題,隨意添加刪除權(quán)限都可以正常動(dòng)作),時(shí)間問題只能以這種方式來講解了,需要深入了解本方案設(shè)計(jì)的朋友請下載整個(gè)系統(tǒng)的源碼來看,如果本文對(duì)你有幫助,請點(diǎn)擊推薦以示支持,謝謝。
在線demo: http://mdms.kudystudio.com/
用戶/密碼:test1/test1 test2/test2 (注:同一用戶在另一瀏覽器登錄,另一用戶在session失效后會(huì)被逼下線)
聯(lián)系客服