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()函数写那些容易出错的代码了,而只要写一段直白的语句标注在相关的属性上。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章