答覆“對CSLA很感興趣,但覺得它的權限管理(操作權限和字段權限)那塊很難做到動態配置,想知道你們是怎麼做的,希望可以交流一下。。。”:
此處的操作權限,可歸爲業務對象的public過程的控制;而字段權限,可歸爲業務對象的public屬性的控制,屬性將字段進行了封裝。
首先不是很清楚你所謂的動態配置是指達到什麼程度,如果相對靜態配置而言是指CSLA作者的那本書裏所提供的寫法的話,那確實是夠累人的,將角色字符串寫死到了代碼裏來做判斷。。。這個做法,在公司的一個超大型項目裏也這麼做了:
string permCode = "A0200002";
if (!UserBLL.CheckRight(permCode))
{
throw new XXXXSecurityException("A020100002", BittInnerBLL.UnallowedAddBitt);
}
這樣的寫法着實讓人無法忍受,permCode字符串一點含義都沒有,只是一個檢索ID,要知道到底是什麼個角色,開發人員得到配置表裏去找。這對於大型系統來說是個災難,工程裏到處是這樣的代碼讓人發暈。
Phenix框架對基於角色的權限控制做了封裝,首先業務開發人員是不必寫一行權限校驗代碼,框架提供給用戶(或實施人員)一個配置工具,將業務類註冊到配置表裏,然後在配置工具界面上將角色與類及其屬性、方法進行綁定即可。。。這樣,完全可以拋棄permCode,用戶可隨時對具體的類進行權限的變更。
不過,還有更復雜的權限控制,那就是業務邏輯的權限控制。
就業務屬性的寫權限問題而言,請注意區分什麼是歸於業務邏輯的寫權限,什麼是歸於角色的寫權限;一般情況下,基於角色的寫權限是靜態的,可以做到區分字段(縱向)的控制,而做不到區分記錄(橫向)的控制(“切片”模式在特定場景下可以實現);很多業務場景下,看似角色權限問題,可以歸爲業務邏輯權限問題來處理。
典型的例子就是在單據的審批流程中,不同階段由不同的角色處理單據上特定的字段,這些字段(通過屬性)的讀寫控制看似和角色有了綁定,其實是應該與業務對象的狀態進行綁定,即可以通過單據狀態(爲單據對象的一個屬性)來控制的。
對業務對象狀態的控制,其實就是對業務流程的控制,而業務流程相對來說是固定的,這可以通過上面的配置工具進行綁定。
如何從業務邏輯上控制對象的某個屬性是否可寫(就是set方法),可以這樣:
1,在業務類上:
public override bool CanWriteProperty(string propertyName)
{
if (String.Compare(propertyName, "XXX", false) == 0) //XXX爲需要控制的屬性名
{
if (!Selected) //未選擇時要求不允許修改XXX屬性;而選擇時雖然業務邏輯允許修改,不過還得過下面的框架關
return false;
}
else if (String.Compare(propertyName, "YYY", false) == 0) //YYY爲需要控制的屬性名
{
if (!Selected) //未選擇時要求不允許修改YYY屬性;而選擇時雖然業務邏輯允許修改,不過還得過下面的框架關
return false;
}
return base.CanWriteProperty(propertyName); //交給框架處理編輯狀態、權限等
}
2,在UI上:
對於屬性隨着業務對象狀態變化而發生的權限控制,可以通過框架控件的barManager.BindingSources裏的BindingSourceStatus來做以下的配置:
BindingSourceStatus.HyperResetAuthorization = true;(缺省爲false)
此時,一旦業務屬性發生任何變動,都將重置相關控件的readonly值,從而做到動態控制權限;
注:1,上述案例,是以業務類的Selected來判斷是否允許寫屬性,你也可以改成其他判斷條件,比如拿業務對象中某些字段來組合出判斷條件等等;
2,注意,當你的邏輯判斷結果爲true時,請繼續讓框架來處理,即調用base.CanWriteProperty(propertyName); 總之,你的return肯定是false,不應該出現return true,否則就會出現權限漏洞;
3,本方法其實是實現行記錄某些字段內容的邏輯寫權限控制;如果把比較propertyName的代碼去掉,僅留下邏輯判斷(比如:if (!Selected)),那麼對屬性的寫權限就是無差別處理了,其實就是對該對象做了寫權限的處理(實現行記錄的邏輯寫權限控制);
4,本方法適用於業務邏輯寫權限處理,對於對象(行記錄)或屬性(行記錄字段)的角色寫權限控制,由框架自動完成,配置方法見框架提供的通用權限配置模塊;
5,寫到這,似乎給了我一個靈感:業務對象的狀態具體實現爲枚舉,那爲什麼不能採取和角色權限控制方法一樣來處理呢,想想怎麼添加這個功能到框架裏。。。這樣,開發人員就不必在CanWriteProperty()函數寫那些容易出錯的代碼了,而只要寫一段直白的語句標註在相關的屬性上。。。