CSLA如何動態控制權限的問題

答覆“對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()函數寫那些容易出錯的代碼了,而只要寫一段直白的語句標註在相關的屬性上。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章