访问控制组件的权限粒度及它跟AOP的恩恩怨怨

访问控制组件的权限粒度及它和AOP的恩恩怨怨
看得人多re的人少,究其原因大约是读者读完以后就miss the point了,不知所云,何来回馈?
so here is the point:

1 访问控制组件的开发在Action层打住还是往下到Service层?

2 是否还能往下到DAO?

3 将Action作为权限元素管控的话,它跟HTTP POST/GET是一一对应关系吗? 它跟URL是一一对应关系吗?

4 AOP是服务性功能,资源树(当然也可以是其他结构)没有初始化之前,AOP无计可施


这几天非常初略的看了一下Acegi,给出如上问题的如下答案,各位指正:
1 Acegi里面没有所谓的Action权限,要么是Web资源,用antURL来进行标识;要么就是业务方法,使用AOP验证

2 没有人这么用过

3 论坛上Robin诸人是这么用的,这里有一个如何初始化Action资源的问题,以后详细来讨论

4 本来想用AOP验证和授权web资源就是错误的想法




就我的感觉设计一个基于RABC的访问控制模型组件的难点不是User-Role-Permission等概念,而是怎样定义和管理资源。
一种说法是:
如果要做一个通用的权限控制模型,由于针对不同的应用,项目中涉及到的资源各不相同,并且每一类资源上的操作也不一样,因此需要抽象出Resource-ResourceType-Operation类出来,为应用开发提供管理资源、资源类型以及定义在资源类型上的操作的接口。这样一来灵活是灵活了,一切皆资源!!好处就是应用开发者可以自定义资源,坏处就是,应用开发者不得不自己定义资源.随时而来的还有,需要为每一类资源指定相关的一组操作,比如文件有执行/读/写/删,页面元素有显示/隐藏/,你甚至可以吧领域对象作为一个资源,或者领域对象的一个方法作为一个资源,或者领域对象所在的包作为一个资源...是不是有点灵活过头了? 而且用户真的需要知道这些吗?

第二种说法:
将资源分为功能性资源和数据性资源,页面Page,页面上的Action(也就是所谓的业务接口,针对用户可见的.它实际上就映射到了页面上的某一个或者一组元素,这个有空再讨论)作为功能性资源,是用户用来进行权限配置的接口,用户只需要了解到这一粒度的权限就可以了,那么针对这个资源,其上的操作只有访问这一种操作,要么有要么没有,管理员(比较高级的用户)给角色分配就好了,so simple.我们把这种权限分配通常叫做前台权限管控.但是往往一个业务接口是由若干个领域对象的方法(在纯OO模型下,如果是贫血的domain模型的话大约就是Service方法吧)组成的一个流程,前后分别是用AOP动态植入的权限验证啊,日志啊,连接的建立与释放啊等等.其中每一个领域对象方法对应着一些数据的操作,无外乎CURD四个.那么针对某一类数据(比如物料)或者某一个数据(料号为ABC的物料,数据实例)的操作我们叫做数据性资源上的权限.当一个业务接口由A对象的create方法+B对象的Update方法组成的话,如果某用户没有对A数据的C(新建)权限,那么此业务接口将不能得到执行,多么强大啊!!问题是,除了用人眼看代码,我怎么能知道业务接口调用了哪些领域对象的哪些方法呢? 虽然在逻辑上, page-Action-dominObject(PO)-domainObjectMethod(Service method)可以组成一个资源树,父资源的权限可以通过子资源的权限计算得到,那么如果我们将用户的权限指定到最细的粒度上,那我们就能计算出某用户针对此资源树上所有的权限了.这个可以参见我的另外一个文章:http://www.iteye.com/post/606826.我们把这叫做后台权限管控但是实际上,我们没有办法初始化这颗权限树啊!
这样的情况下,AOP失效,为什么 ? 因为AOP太早了.如果我不知道一个业务接口中到底调用了那些领域对象方法,我就不能找到这些领域对象方法资源的资源ID并传给AOP,那么AOP中的权限验证接口方法通过什么来判断呢?


坛子里面基本上所有有关RBAC的讨论我都读过了,针对Action做资源管控的或者继续往下针对数据资源进行管控的都有,但是都没有给出可行的方案或者结论.我考虑后台权限管控的原因在于怕有人绕过UI,跳过业务接口直接调用领域模型的方法,但是转念想想又可笑,那有人直接绕过应用操作数据库呢? AC系统不是万能,那么他的系统边界又应该如何定义呢?
1 楼 Joo 2008-08-24  
可能是上面的长篇大论吓着大家了,简单来说就是如果除了对业务借口进行权限管控外,还需要对领域对象方法这一粒度的资源作权限设定和管控应该怎么做
2 楼 Joo 2008-08-27  
这里暂且不谈数据行的管控,这个到底要不要纳入AC系统范畴,或者只是根据业务规则来处理,现在JE上还没有令人信服的定论
3 楼 Joo 2008-09-09  
另外就是感觉Acegi中的使用annonation来进行业务方法的管控太死板了,完全没有可灵活配置的余地,而且每次都要重新编译发布成本太高.在我自己的ac组件中也有做注释,但是只是为每一个Action做一个中文描述,用以在UI界面上用户对权限进行配置的时候可以看到每一个Action都是干什么的,而不是纯粹的难以理解的"包路径.类名.方法名"的方式
4 楼 downpour 2008-09-09  
权限理论本身就是很复杂的理论,完全取决于项目的需要。

我不认为存在着一种模型可以覆盖所有的权限内容。因为权限是一个综合概念,不仅仅存在于访问或者可见级别。

Acegi的好处在于它可以用用户-权限-资源的多对多关系来定义关系模型,从而抽象出可访问或者可见的不同级别和类型。而且Acegi提供了很多不同的工具类,从而提供了很多不同层次的整合方向。比如,我就是将Acegi与Struts的Interceptor整合来控制页面上元素的可见性。

另外,权限可能与登录人的自然属性有关,比如,某个人只能看到他所属部门、所属公司的男性的数据。此时,可能这些自然属性需要被动态拼到SQL中去,那么这种动态拼SQL的情况就需要自己来实现,任何框架都帮不了你的忙了。
5 楼 Joo 2008-09-09  
Acegi中web资源和业务方法资源是利用角色来管控的,业务对象资源是使用ACL思想来管理的.这么做的肯定是这两种资源在某些地方不相同,但有一点相同的就是他们都只能对资源管控(不管是简单的访问与否或者复杂的RUCD),而不能对资源作出跟实际项目耦合的业务规则划分(楼上朋友的最后一段)

但是跟现在实际相比,Acegi的这种权限模型怎么都不能被很好的用起来,大部分的应用都是针对Action来做权限管控的
http://www.iteye.com/topic/17896?page=1
可以说是恰恰处在Web资源和业务方法资源中间的那一层资源,好像Acegi对此无能为力啊
我的观点robbin很好的阐述出来
引用

我确实不了解Acegi,但是我觉得有一个基本原则,就是一般应用程序的权限判断应该在web层控制,我看了好几个Acegi示例,都是对业务bean的 method进行拦截和权限控制。对业务bean的method进行权限控制,首先粒度就有问题,大多数情况下粒度太细,但有些情况又可能太粗。其次,权限判别完成以后,如果权限拒绝,你怎么把信息有效的传递给Web层和其他的Facade层进行用户友好性的提示处理?如果直接断掉调用链,Web层调用到这里突然就没有任何反应了;如果抛出运行期异常(也只能抛运行期异常),Web层未必能够清楚的了解到究竟会出现哪些和权限有关的异常,那么大量使用 try catch去捕获处理,代码就会非常烦琐。考虑到权限控制往往和用户交互非常紧密,因此应该尽量往前推到用户交互层去做,而不是底层。而且很多系统需要根据权限不同,生成不同的UI组件(例如管理员的菜单和普通用户菜单就肯定不一样),这也需要在Web层的View进行控制。

总之,我到不是对Acegi有什么偏见,我希望看到的是Acegi对Web Action的权限控制示例,而不是对业务bean的method级别控制,但是还没有看到任何这样的示例。


但是又跟他提出的解决方法有点不一样,因为我不用struct,所以在我的代码中没有真正的XXXAction类的声明,从而不能继承一个hasPermission接口让Action自己来处理权限验证判断.我能做的就是将一个应用中所有的Action(概念上的)收集起来(在我们现在自己用的mvc框架下,就是每一个jsp页面对应一个后台java类,有点类似jsf中的受控BEAN.Action就是这些java类上的方法),然后交给用户自行分配权限.那么就此来说,至少应该维护两张表: Action(也就是权限)-角色关联表,Action表.
6 楼 downpour 2008-09-09  
因为你的url可以定义为资源,而url与Action是有对应关系的,所以Acegi同样可以在Action级别做权限控制。除了业务级别的权限控制,Acegi基本可以覆盖大部分的访问级别控制。
7 楼 Joo 2008-09-09  
downpour 写道
因为你的url可以定义为资源,而url与Action是有对应关系的,所以Acegi同样可以在Action级别做权限控制。除了业务级别的权限控制,Acegi基本可以覆盖大部分的访问级别控制。


能详细说说URL-Action如何对应吗
因为在我看来url和action并不太适合建立稳定的对应关系

另外,我觉得这样的做法比较生硬.我的本意是将Action作为权限资源进行管控,结果为了要使用Acegi,偏偏要把它跟URL关联起来,很扭曲啊.说说我的解决方法:

1 建立注释,用以描述某一个Action的具体意义,便于权限管理员理解并进行分配
package com.kop.scm.ac.core;
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Permission {
    String des();
}


2 开发Action后,要做一点点小工作就是为这个Action方法加上描述标注
public class Login {

    @Permission(des = "login into the system")
    public String login(Map mapRequest, Map mapSession) {
        System.out.println("logining...");
        return FormStatics.ACTIONRETURN_REDIRECT + "Index.jsp";
    }
}


3 写一个ServletContextLisenter在应用启动时利用反射读出应用中所有的Action以及它对应的描述信息
4 持久化此Action表
5 提供UI界面让权限管理员来针对每个角色指定可以执行的Action元素
8 楼 Joo 2008-09-10  
改进了一下,吸收Acegi的做法是用XML保存Action资源,就类似Acegi中的DefinitionSource,由开发人员自行进行配置然后再应用启动时读入内存
9 楼 popufig 2009-01-02  
我的想法和你的很类似,不过遭到同事的强烈反对
http://popufig.iteye.com/admin/blogs/305872

其实你的做法相当与把resource+operation合并为一个点,也就是你的action,这种做法有个限制就是如果一个action有多个用户可以调到的方法(struts的dispatchAction),而且要求权限不一致,就很郁闷了

我的想法是把action或者是form做为资源,里面不同的方法对应不同的操作,发布后把这种资源和操作持久化到数据库中,授权时可以用树状结构来显示,实际就两层,第一层是这些资源,第二层就是对应这些资源所能做的操作。
10 楼 Joo 2009-01-04  
不知道楼上兄弟说的一个action有多个用户可调用的方法是意思,在我的模型中action是最小的权限粒度,它本身就是一个方法,哪里还会更小的组合?
11 楼 SINCE1978 2009-06-05  
干嘛要用acl这么麻烦,我们可以要求使用权限系统的客户在设计他们的业务表的时候增加录入人字段,或者录入者所属组织机构字段。使业务数据都有所属关系,然后剩下的就不用说了吧。