很久以前就嘗試過
使用AOP進行權限控制的管理
,那時候只是試試而已,并沒有在項目中應用過,最近跟的一個B/S項目中要求我們把權限管理加進去,于是我考慮以前的AOP方法是否真的可行。思考許久后的結(jié)果是,可行,但是太麻煩。
主要原因在于需要在UI層<=>邏輯層<=>數(shù)據(jù)層之外增加額外的一層來使得AOP攔截可以以恰當?shù)牧6取⑶‘數(shù)臅r機切入。如果不增加額外的這一層而使用AOP就可能會得到這樣的結(jié)果--比如,在業(yè)務邏輯層或數(shù)據(jù)層使用AOP切入,就有可能出現(xiàn)這樣的情形,用戶花了老大的勁將要錄入的信息敲入了,最后當點擊“提交”時,系統(tǒng)卻提示說“你沒有權限進行添加操作!”。如果你是這個用戶,你一定會郁悶得吐血!
所以,如果系統(tǒng)不允許用戶添加,則根本就不應該讓添加的Page或Form出現(xiàn)在用戶眼前,然而,這在邏輯層或數(shù)據(jù)層是無法獲取這個信息的,只有UI層知道這是發(fā)生在什么時刻。但是,在UI層使用AOP截獲,你看見過么?我沒有,我相信那不是一件容易做的工作。
于是,我開始尋找AOP之外的方法,終于,我找到了一個自己還比較滿意的解決方案。下面我們以B/S系統(tǒng)為例,來詳細描述這個方案,如果是C/S系統(tǒng),可以類推之。
為了構建一個在不同B/S系統(tǒng)中可以復用的解決方案,我們需要規(guī)范化(定義)一些基礎設施或元素。首先,我們需要定義權限的類別,比如最常見的有瀏覽、添加、修改、刪除。你也許已經(jīng)想到使用一個枚舉就可以了。但是,不能使用枚舉,因為枚舉是sealed,不能被繼承,這就意味著權限類別將不能被自定義擴展,所以,我沒有使用enum,而是使用class。
主要原因在于需要在UI層<=>邏輯層<=>數(shù)據(jù)層之外增加額外的一層來使得AOP攔截可以以恰當?shù)牧6取⑶‘數(shù)臅r機切入。如果不增加額外的這一層而使用AOP就可能會得到這樣的結(jié)果--比如,在業(yè)務邏輯層或數(shù)據(jù)層使用AOP切入,就有可能出現(xiàn)這樣的情形,用戶花了老大的勁將要錄入的信息敲入了,最后當點擊“提交”時,系統(tǒng)卻提示說“你沒有權限進行添加操作!”。如果你是這個用戶,你一定會郁悶得吐血!
所以,如果系統(tǒng)不允許用戶添加,則根本就不應該讓添加的Page或Form出現(xiàn)在用戶眼前,然而,這在邏輯層或數(shù)據(jù)層是無法獲取這個信息的,只有UI層知道這是發(fā)生在什么時刻。但是,在UI層使用AOP截獲,你看見過么?我沒有,我相信那不是一件容易做的工作。
于是,我開始尋找AOP之外的方法,終于,我找到了一個自己還比較滿意的解決方案。下面我們以B/S系統(tǒng)為例,來詳細描述這個方案,如果是C/S系統(tǒng),可以類推之。
為了構建一個在不同B/S系統(tǒng)中可以復用的解決方案,我們需要規(guī)范化(定義)一些基礎設施或元素。首先,我們需要定義權限的類別,比如最常見的有瀏覽、添加、修改、刪除。你也許已經(jīng)想到使用一個枚舉就可以了。但是,不能使用枚舉,因為枚舉是sealed,不能被繼承,這就意味著權限類別將不能被自定義擴展,所以,我沒有使用enum,而是使用class。
///
<summary>
/// 應用可以擴展PermissionType,以增加其它權限類別,比如審核等
/// 自定義類別取值應大于5
/// </summary
publicclassPermissionType
{
public const int Browse = 1 ;
public const int Add = 2 ;
public const int Update = 3 ;
public const int Delete = 4 ;
}
/// 應用可以擴展PermissionType,以增加其它權限類別,比如審核等
/// 自定義類別取值應大于5
/// </summary
publicclassPermissionType
{
public const int Browse = 1 ;
public const int Add = 2 ;
public const int Update = 3 ;
public const int Delete = 4 ;
}
這樣,如果具體應用中有更多的權限類別,只要從PermissionType繼承即可。比如,應用中需要添加“審核”、“消審”的權限,則可以
public
class
MGPPermissionType:PermissionType
{
public const int Audit = 10 ; // 審核
public const int CancelAudit = 11 ; // 消審
}
{
public const int Audit = 10 ; // 審核
public const int CancelAudit = 11 ; // 消審
}
一個用戶所擁有的權限可以使用IPermission接庫進行規(guī)范:
///
<summary>
/// 應用可以擴展IPermission,以增加其它權限類別,比如審核等
/// </summary>
public interface IPermission
{
bool CanBrowse{ get ;}
bool CanAdd{ get ;}
bool CanUpdate{ get ;}
bool CanDelete{ get ;}
}
/// 應用可以擴展IPermission,以增加其它權限類別,比如審核等
/// </summary>
public interface IPermission
{
bool CanBrowse{ get ;}
bool CanAdd{ get ;}
bool CanUpdate{ get ;}
bool CanDelete{ get ;}
}
如果應用需要增加別的權限,也可以在實現(xiàn)這個接口的類中進行擴展,比如
GeneralPermission
GeneralPermission擴展了IPermission接口,添加了“審核”、“消審”的權限。
在B/S系統(tǒng)中,如果用戶要求做一件沒有權限的事情時,通常會轉(zhuǎn)到一個給出提示信息“沒有相應權限”的page。但是,當用戶沒有權限時,到底該怎么做,我們把這個權利留給具體的應用,這里只是用接口來規(guī)范它:
PermissionHelper
好了,一切準備就緒,主角可以出場了,PermissionController--所有與權限相關的操作都有它來轉(zhuǎn)發(fā),如果權限滿足,則調(diào)用目標操作或轉(zhuǎn)到目標頁面;如果條件不滿足,就調(diào)用IPermissionHelper.OnHaveNoPermission方法,一切清晰明了。
PermissionController
Excute方法之所以重載是因為,如果條件滿足,應用通常是兩種反應:
(1)轉(zhuǎn)到用戶想進入的某個page
(2)執(zhí)行用戶希望的某個方法/操作
實際上,緊緊使用第二個Excute已經(jīng)可以包含一切了,第一個Excute是為了簡化通常情況(進入的某個page)的操作。
有了PermissionController,我們的工作會輕松很多,比如,在沒有使用PermissionController的時候,我們經(jīng)常這樣做:
使用PermissionController后,主要這樣就可以了:
原來需要六行代碼,現(xiàn)在一行就搞定了。(關于SessionHelper的信息,請參見 這里 )
我們小結(jié)一下,看看使用PermissionController還會帶來哪些好處:
(1)將原來分散的權限控制,全部集中起來了。
(2)應用中對權限控制所需的代碼量大大減少。
(3)如果要改變系統(tǒng)針對權限不滿足時所進行的動作,只要改變IPermissionHelper.OnHaveNoPermission方法的實現(xiàn)就可以了,而不是要到每個page中修改。
(4)擴展/修改權限類別非常方便。
你可以把PermissionController的實現(xiàn)和相關接口定義拷貝到自己的類庫中,然后在項目中使用。也可以直接使用 ESFramework (V0.1+)的ESFramework.Web.PermissionController類。
歡迎你和我討論關于權限控制的更多更好的解決方案, agilesoft@163.com 。

在B/S系統(tǒng)中,如果用戶要求做一件沒有權限的事情時,通常會轉(zhuǎn)到一個給出提示信息“沒有相應權限”的page。但是,當用戶沒有權限時,到底該怎么做,我們把這個權利留給具體的應用,這里只是用接口來規(guī)范它:
public
interface
IPermissionHelper
{
void OnHaveNoPermission( int pType,HttpResponseresponse);
bool VerifyCustomPermission(IPermissionper, int pType); // 驗證自定義的權限類型
}
OnHaveNoPermission方法就是應用在用戶沒有權限操作時定義要做的事情。通過上面的介紹,VerifyCustomPermission方法的作用就一幕了然了。比如下面這個IPermissionHelper實現(xiàn):
{
void OnHaveNoPermission( int pType,HttpResponseresponse);
bool VerifyCustomPermission(IPermissionper, int pType); // 驗證自定義的權限類型
}

好了,一切準備就緒,主角可以出場了,PermissionController--所有與權限相關的操作都有它來轉(zhuǎn)發(fā),如果權限滿足,則調(diào)用目標操作或轉(zhuǎn)到目標頁面;如果條件不滿足,就調(diào)用IPermissionHelper.OnHaveNoPermission方法,一切清晰明了。

Excute方法之所以重載是因為,如果條件滿足,應用通常是兩種反應:
(1)轉(zhuǎn)到用戶想進入的某個page
(2)執(zhí)行用戶希望的某個方法/操作
實際上,緊緊使用第二個Excute已經(jīng)可以包含一切了,第一個Excute是為了簡化通常情況(進入的某個page)的操作。
有了PermissionController,我們的工作會輕松很多,比如,在沒有使用PermissionController的時候,我們經(jīng)常這樣做:
privatevoidDataGrid1_ItemCommand(objectsource,System.Web.UI.WebControls.DataGridCommandEventArgse)
{
stringid=e.Item.Cells[0].Text;
if(e.CommandName=="ButtonUpdate")
{
if(!SessionHelper.CreateInstance(this.Session).UserRoleCollection.AdminSubSystemPermission.CanUpdate)
{
this.Response.Redirect("../ErrorInfoForm.aspx");
return;
}
this.Response.Redirect("CQProjectPhaseForm.aspx?ID="+id);
}
}
{
stringid=e.Item.Cells[0].Text;
if(e.CommandName=="ButtonUpdate")
{
if(!SessionHelper.CreateInstance(this.Session).UserRoleCollection.AdminSubSystemPermission.CanUpdate)
{
this.Response.Redirect("../ErrorInfoForm.aspx");
return;
}
this.Response.Redirect("CQProjectPhaseForm.aspx?ID="+id);
}
}
使用PermissionController后,主要這樣就可以了:
privatevoidDataGrid1_ItemCommand(objectsource,System.Web.UI.WebControls.DataGridCommandEventArgse)
{
stringid=e.Item.Cells[0].Text;
GeneralPermissiongp=SessionHelper.CreateInstance(this.Session).UserRoleCollection.AdminSubSystemPermission;
if(e.CommandName=="ButtonUpdate")
{
Global.PermissionController.Excute(gp,MGPPermissionType.Update,this.Response,"CQProjectPhaseForm.aspx?ID="+id);
}
{
stringid=e.Item.Cells[0].Text;
GeneralPermissiongp=SessionHelper.CreateInstance(this.Session).UserRoleCollection.AdminSubSystemPermission;
if(e.CommandName=="ButtonUpdate")
{
Global.PermissionController.Excute(gp,MGPPermissionType.Update,this.Response,"CQProjectPhaseForm.aspx?ID="+id);
}
原來需要六行代碼,現(xiàn)在一行就搞定了。(關于SessionHelper的信息,請參見 這里 )
我們小結(jié)一下,看看使用PermissionController還會帶來哪些好處:
(1)將原來分散的權限控制,全部集中起來了。
(2)應用中對權限控制所需的代碼量大大減少。
(3)如果要改變系統(tǒng)針對權限不滿足時所進行的動作,只要改變IPermissionHelper.OnHaveNoPermission方法的實現(xiàn)就可以了,而不是要到每個page中修改。
(4)擴展/修改權限類別非常方便。
你可以把PermissionController的實現(xiàn)和相關接口定義拷貝到自己的類庫中,然后在項目中使用。也可以直接使用 ESFramework (V0.1+)的ESFramework.Web.PermissionController類。
歡迎你和我討論關于權限控制的更多更好的解決方案, agilesoft@163.com 。
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
