曾经爱晚人








永远自由的心

AOP实现分离权限关注 - 补遗

昨天的Blog中我描述了使用AOP分离权限关注的基本做法。回家仔细想了想,把思考的结果补充一下。

我们知道,在基本的RBAC模型中有以下基本(接口)对象:Domain, Group, User, Role, Privilege, Operation, Resource以及对外的SecurityManager。Privilege通过Operate Resource而产生,Role则对应若干个Privilege。不同的Domain, Group, User拥有不同数量的Role,其中User的Role可以继承自Group,也可以继承自Domain;Group的权限可以继承自Domain。对外表现时,可以简单地通过SecurityMananger.checkPermission(User,  Privilege)的返回值true/false进行判断。上面每个对象都是接口,SecurityManager可以通过IoC反向注入,从而使得这种权限模型的使用比较灵活。

在实际情况中,这种权限系统中Resource的定义方法与粒度最难以控制。不同的业务系统中可能有不同的定义方式。而且这种方式的交流非常不方便。以一个普通的“科研项目管理”项目为例:系统中需要进行权限控制的东西可能有:用户信息(增删改查),项目信息(增删改查),日志信息(查看,统计)等等。这种权限的控制如果按照垂直编程的方式来写,需要进行以下工作:

研究:需要控制的资源到底是什么?用户信息?项目信息?这些东西如何表现?这个问题在这种模型中很难考虑清楚。最终的结果往往是,使用没有Resource接口的权限模型,形成一份新的文档:权限代码以及对应说明表。每个编程人员在编写相应的业务逻辑时,都需要参考这个表,并将程序中加上一序列的if --- else来判断权限。这种做法无疑是危险的。因为一旦权限代码发生变动, 这个业务方法马上得重写。稍微考虑不难知道,这种方法根本不可取:连基于URI的解决方案都不如。

可以看到,像用户信息、项目信息等等,都是业务对象,这些业务对象对于人是可理解的,但将这些业务对象作为RBAC中的资源是不合理的。因此我提出一种新的资源概念:将具体业务类、业务方法作为RBAC模型中的资源。这样才能够真正脱离权限与业务逻辑。具体做法是:将所有的业务方法名称以及对应的角色名称存入到XML文件或者数据库中,形成一个Resource库:

Method                   Role
------------------------------------------
UserManager.*            UserManager
UserManager.update       UserManager
UserManager.update       User
LogInfo.view             *
LogInfo.statistics       LogManager
...                      ...
------------------------------------------

对于权限的判断,可以在RBAC的具体实现中进行。这里假定有一个SecurityManager.checkPermission(User, Privilege)(这里的Privilege实际上就是能否执行特定业务方法)的方法。根据这个方法,制作一个Aspect:

public class PermissionCheckAdvice implements MethodBeforeAdvice {
    public void before(Method arg0, Object[] arg1, Object arg2)  throws Throwable {
          if (!SecurityManager.checkPermission(User, Privilege)) {
                throws new PermissionDeniedException(User, Privilege);
          }
    }
}

然后使用AOP将这个Advice应用到所有的业务方法(类或者方法可能在具有普遍意义的一个package中,也可能具有一定正则意义),并截获所有的PermissionDeniedException:

public class PermissionThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing(Method method, Object[] args, Object target,
            Throwable subclass) {
        //对Permission Denied Exception进行自己的处理。
    }

}

对应的Spring Beans配置请参考上一片Blog。

AOP分离权限关注的文字到此截至,有些比较重要但是来不及完成的如SecurityManager如何引入,上下文环境如何取得等等,可能需要各位自行完成了。这里提出的是一种将Method作为资源的概念,希望对做权限系统的同仁有所帮助。

发表于 2004年7月23日 10:10

评论

# re: AOP实现分离权限关注 - 补遗

虽然有些代码的例子,不过还是不是很明白,至于其中提到的SecurityManager如何取得上下文环境我倒觉得可以把上下文环境放在ThreadLocal中.........
可能还是得去试着用用才知道怎么用
2004-7-23 14:28 | BlueDavy

# re: AOP实现分离权限关注 - 补遗

这种实现我也考虑过,不过后来觉得不太自然。

主要原因就是resource的取得。 在这个Aspect中,
取不到相应的resource——我是指News, Article, 等等这样的DomainObject。而只能用Service作为Resource来代替。

感觉不是很爽。 另外,我在potain的blog看过一句话,
“要让服务依赖于业务”,恍然大悟。
意思是让权限控制组件依赖于订单,新闻阅览等组件,把那些部分注射到权限控制的组件中。
俺现在正在考虑更大粒度的AOP和权限控制组件,还没有头绪,嘿嘿

希望一起研究~

posted on 2006-01-18 00:56  e旋风  阅读(932)  评论(0编辑  收藏  举报

导航