安全涉及到两个不同的概念,认证和授权。前者是关于确认用户是否确实是他们所宣称的身份。授权则是关于确认用户是否有允许执行一个特定的操作。
在acegi安全系统中,需要被认证的用户,系统或代理称为"principal"。acegi安全系统和其他的安全系统不同,它并没有角色和用户组的概念。
acegi系统设计
关键组件
acegi安全系统包含以下七个关键的功能组件:
l authentication对象,包含了principal,credential和principal的授权信息。同时还可以包含关于发起认证请求的客户的其他信息,如ip地址。
2 contextholder对象,使用threadlocal储存authentication对象的地方。
3 authenticationmanager,用于认证contextholder中的authentication对象。
4 accessdecissionmanager,用于授权一个特定的操作。
5 runasmanager,当执行特定的操作时,用于选择性地替换authentication对象。
6 secure object拦截器,用于协调authenticationmanager,accessdecissionmanager,runasmanager和特定操作的执行。
7 objectdefinitionsource,包含了特定操作的授权定义。
这七个关键的功能组件的关系如下图所示(图中灰色部分是关键组件):
安全管理对象
acegi安全系统目前支持两类安全管理对象。
第一类的安全管理对象管理aop alliance的methodinvocation,开发人员可以用它来保护spring容器中的业务对象。为了使spring管理的bean可以作为methodinvocation来使用,bean可以通过proxyfactorybean和beannameautoproxycreator来管理,就像在spring的事务管理一样使用。
第二类是filterinvocation。它用过滤器(filter)来创建,并简单地包装了http的servletrequest,servletresponse和filterchain。filterinvocation可以用来保护http资源。通常,开发人员并不需要了解它的工作机制,因为他们只需要将filter加入web.xml,acegi安全系统就可以工作了。
安全配置参数
每个安全管理对象都可以描述数量不限的各种安全认证请求。例如,methodinvocation对象可以描述带有任意参数的任意方法的调用,而filterinvocation可以描述任意的http url。
acegi安全系统需要记录应用于每个认证请求的安全配置参数。例如,对于bankmanager.getbalance(int accountnumber)方法和bankmanager.approveloan(int applicationnumber)方法,它们需要的认证请求的安全配置很不相同。
为了保存不同的认证请求的安全配置,需要使用配置参数。从实现的视角来看,配置参数使用configattribute接口来表示。acegi安全系统提供了configattribute接口的一个实现,securityconfig,它把配置参数保存为一个字符串。
configattributedefinition类是configattribute对象的一个简单的容器,它保存了和特定请求相关的configattribute的集合。
当安全拦截器收到一个安全认证请求时,需要决定应用哪一个配置参数。换句话说,它需要找出应用于这个请求的configattributedefinition对象。这个查找的过程是由objectdefinitionsource接口来处理的。这个接口的主要方法是public configattributedefinition getattributes(object object),其中object参数是一个安全管理对象。因为安全管理对象包含有认证请求的详细信息,所以objectdefinitionsource接口的实现类可以从中获得所需的详细信息,以查找相关的configattributedefiniton对象。
acegi如何工作
为了说明acegi安全系统如何工作,我们设想一个使用acegi的例子。通常,一个安全系统需要发挥作用,它必须完成以下的工作:
l 首先,系统从客户端请求中获得principal和credential;
2 然后系统认证principal和credential信息;
3 如果认证通过,系统取出principal的授权信息;
4 接下来,客户端发起操作请求;
5 系统根据预先配置的参数检查principal对于该操作的授权;
6 如果授权检查通过则执行操作,否则拒绝。
那么,acegi安全系统是如何完成这些工作的呢?首先,我们来看看acegi安全系统的认证和授权的相关类图:
图中绿色部分是安全拦截器的抽象基类,它包含有两个管理类,authenticationmanager和accessdecisionmanager,如图中灰色部分。authenticationmanager用于认证contextholder中的authentication对象(包含了principal,credential和principal的授权信息);accessdecissionmanager则用于授权一个特定的操作。
下面来看一个methodsecurityinterceptor的例子:
<bean id="bankmanagersecurity"
class="net.sf.acegisecurity.intercept.method.methodsecurityinterceptor">
<property name="validateconfigattributes">
<value>true</value>
</property>
<property name="authenticationmanager">
<ref bean="authenticationmanager"/>
</property>
<property name="accessdecisionmanager">
<ref bean="accessdecisionmanager"/>
</property>
<property name="objectdefinitionsource">
<value>
net.sf.acegisecurity.context.bankmanager.delete*=
role_supervisor,run_as_server
net.sf.acegisecurity.context.bankmanager.getbalance=
role_teller,role_supervisor,banksecurity_customer,run_
</value>
</property>
</bean>
上面的配置文件中,methodsecurityinterceptor是abstractsecurityinterceptor的一个实现类。它包含了两个管理器,authenticationmanager和accessdecisionmanager。这两者的配置如下:
<bean id="authenticationdao" class="net.sf.acegisecurity.providers.dao.jdbc.jdbcdaoimpl">
<property name="datasource"><ref bean="datasource"/></property>
</bean>
<bean id="daoauthenticationprovider"
class="net.sf.acegisecurity.providers.dao.daoauthenticationprovider">
<property name="authenticationdao"><ref bean="authenticationdao"/></property>
</bean>
<bean id="authenticationmanager" class="net.sf.acegisecurity.providers.providermanager">
<property name="providers">
<list><ref bean="daoauthenticationprovider"/></list>
</property>
</bean>
<bean id="rolevoter" class="net.sf.acegisecurity.vote.rolevoter"/>
<bean id="accessdecisionmanager" class="net.sf.acegisecurity.vote.affirmativebased">
<property name="allowifallabstaindecisions"><value>false</value></property>
<property name="decisionvoters">
<list><ref bean="rolevoter"/></list>
</property>
</bean>
准备工作做好了,现在我们来看看acegi安全系统是如何实现认证和授权机制的。以使用http basic认证的应用为例子,它包括下面的步骤:
1. 用户登录系统,acegi从acegisecurity.ui子系统的安全拦截器(如basicprocessingfilter)中得到用户的登录信息(包括principal和credential)并放入authentication对象,并保存在contextholder对象中;
2. 安全拦截器将authentication对象交给authenticationmanager进行身份认证,如果认证通过,返回带有principal授权信息的authentication对象。此时contextholder对象的authentication对象已拥有principal的详细信息;
3. 用户登录成功后,继续进行业务操作;
4. 安全拦截器(bankmanagersecurity)收到客户端操作请求后,将操作请求的数据包装成安全管理对象(filterinvocation或methodinvocation对象);
5. 然后,从配置文件(objectdefinitionsource)中读出相关的安全配置参数configattributedefinition;
6. 接着,安全拦截器取出contextholder中的authentication对象,把它传递给authenticationmanager进行身份认证,并用返回值更新contextholder的authentication对象;
7. 将authentication对象,configattributedefinition对象和安全管理对象(secure object)交给accessdecisionmanager,检查principal的操作授权;
8. 如果授权检查通过则执行客户端请求的操作,否则拒绝;
accessdecisionvoter
注意上节的accessdecisionmanager是一个affirmativebased类,它对于用户授权的投票策略是,只要通过其中的一个授权投票检查,即可通过;它的allowifallabstaindecisions属性值是false,意思是如果所有的授权投票是都是弃权,则通不过授权检查。
acegi安全系统包括了几个基于投票策略的accessdecisionmanager,上节的rolevoter就是其中的一个投票策略实现,它是accessdecisionvoter的一个子类。accessdecisionvoter的具体实现类通过投票来进行授权决策,accessdecisionmanager则根据投票结果来决定是通过授权检查,还是抛出accessdeniedexception例外。
accessdecisionvoter接口共有三个方法:
public int vote(authentication authentication, object object, configattributedefinition config);
public boolean supports(configattribute attribute);
public boolean supports(class clazz);
其中的vote方法返回int返回值,它们是accessdecisionvoter的三个静态成员属性:access_abstain,,access_denied和access_granted,它们分别是弃权,否决和赞成。
acegi安全系统中,使用投票策略的accessdecisionmanager共有三个具体实现类:affirmativebased、consensusbased和unanimousbased。它们的投票策略是,affirmativebased类只需有一个投票赞成即可通过;consensusbased类需要大多数投票赞成即可通过;而unanimousbased类需要所有的投票赞成才能通过。
rolevoter类是一个acegi安全系统accessdecisionvoter接口的实现。如果configattribute以role_开头,rolevoter则进行投票。如果grantedauthority的getautority方法的string返回值匹配一个或多个以role_开头的configattribute,则投票通过,否则不通过。如果没有以role_开头的configattribute,rolevoter则弃权。
安全拦截器
拦截器如何工作
methodinvocation拦截器
filterinvocation拦截器
认证
认证请求
认证管理器
authentication provider
授权
access decision manager
voting decision manager
授权管理推荐
contextholder的用户接口
用户接口目标
http会话认证
http basic认证
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



