洗洗就睡了
催眠曲进行中
农妇,山泉,有点田
我的首页
文章
相册
圈子
留言
管理
 
    当前所在页面:首页>>文章>>Acegi 系统使用回顾
Acegi 系统使用回顾
    作者: 来源: 发表时间:2008-03-30

 
 

简单回顾一下acegi secrutiy在Sitebuilder的应用

acegi的正确发音为a see gee,取自某位希腊天神的名字。想想一直都叫他a c  e g i ,幸亏他名儿不叫a....z不然要累死我 :)

我们在LPP项目中使用到了JAAS系统,相对acegi来说,它比较容易搭建和配置。但需要把resource的访问许可定义在web.xml的security contrain单元中。然后利用loginmodule返回用户的principles进行权限匹配。

而spring家族的acegi 安全系统 利用拦截器提供对url或方法级更加细粒度的权限判断,用户可以结合自己的权限系统灵活配置资源,角色,permission之间的关系。

不过令人头疼就是那一群filter组件配置。

<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
  <property name="filterInvocationDefinitionSource">
   <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,

rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
   </value>
  </property>
</bean>

acegi采用农夫山泉的层层过滤方式对url的访问进行权限检查。各filter的解释可以参看http://xanbio.blog.163.com/blog/static/18424783200772410421614/ 。这个哥哥做了很不错的解释。

下面内容定义了AuthenticationProcessingFilter的配置。包括验证管理器定义,登陆失败返回页,默认成功页,登陆窗action地址,莫忘我服务。

<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="authenticationFailureUrl" value="/login.ejf?easyJWebCommand=loginErr"/>
  <property name="defaultTargetUrl" value="/login.ejf?easyJWebCommand=loginSuccess"/>
  <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
  <property name="rememberMeServices" ref="rememberMeServices"/>
</bean>

一个常用的安全系统登陆过程常有两步:验证和授权。 acegi则对访问资源的用户进行用户和权限判断。

下面来定义验证管理器。

<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref local="daoAuthenticationProvider"/>
                <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
                    <property name="key" value="changeThis"/>
                </bean>
                <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
                    <property name="key" value="changeThis"/>
                </bean>
            </list>
        </property>
    </bean>

dao验证提供类包含了userdetails服务类,usercache,密码加密类

    <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userDetailsService"/>  《===引用userDetailsService
        <property name="userCache"> .....
         <property name="passwordEncoder"><bean class="uk.salford.ian.site.security.MD5PasswordEncoder"/></property>
    </bean>

    <bean id="userDetailsService" class="uk.salford.ian.site.security.JpaUserService">
        <property name="userService" ref="userService"/>
    </bean>

而userDetailsService服务是一个自实现类uk.salford.ian.site.security.JpaUserService。 它实现org.acegisecurity.userdetails.UserDetailsService接口,提供 loadUserByUsername方法,根据用户名返回 UserDetails 对象 。UserDetails 中包括基本的用户信息,并且我们提供了方法去读取用户拥有的权限。

public UserDetails loadUserByUsername(String userName)

{User user = userService.loadUserByName(userName);

return User;

}

public class User implements Principal, UserDetails {

public GrantedAuthority[] getAuthorities() {       
        if (authorities == null)
            reloadAuthorities();  //调用reloadAuthorities获得一系列用户相应的权限。
        return authorities;
    }

    public void reloadAuthorities() {
     .... 具体的权限返回逻辑。

    }

}

通过以上的实现,我们在读取用户的时候,也可以读取它所拥有的资源访问权限。在访问一个系统资源的时候,拦截器首先会读取可访问这个资源的许可,与用户的访问许可作对比,从而实现判断。

FilterInvocationInterceptor
该Filter 会首先调用AuthenticationManager判断用户是否已登陆认证,如还没认证成功,则重定向到登陆界面.认证成功,则从 Authentication中获取用户的权限.然后从objectDefinitionSource属性获取各种URL资源所对应的权限.最后调用 AccessDecisionManager来判断用户所拥有的权限与当前受保护的URL资源所对应的权限是否相匹配.如果匹配失败,则返回403错误给 用户.匹配成功则用户可以访问受保护的URL资源

<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="accessDecisionManager">
            <bean class="org.acegisecurity.vote.AffirmativeBased">
                <property name="allowIfAllAbstainDecisions" value="false"/>
                <property name="decisionVoters">
                    <list>
                        <bean class="org.acegisecurity.vote.RoleVoter"/>
                        <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
                    </list>
                </property>
            </bean>
        </property>
        <property name="objectDefinitionSource" ref="myFilterDefinition    </property>    </bean>

<bean id="myFilterDefinition" class="uk.salford.ian.site.security.MyFilterSourceDefinition">
<property name="securityService" ref="securityService"/>
</bean>

MyFilterSourceDefinition 是继承于抽象类AbstractFilterInvocationDefinitionSource 。主要实现三个方法:

ConfigAttributeDefinition getAttributes(Object object)
          Accesses the ConfigAttributeDefinition that applies to a given secure object. 

abstract  ConfigAttributeDefinition lookupAttributes(String url)
          Performs the actual lookup of the relevant ConfigAttributeDefinition for the specified FilterInvocation.

supports(Class clazz)
          Indicates whether the ObjectDefinitionSource implementation is able to provide ConfigAttributeDefinitions for the indicated secure object type.

 lookupAttributes方法中,我们返回相应url的许可列表。

做完这步,基于acegi secrutiy的权限系统框架都基本搭成了。

 
 

(阅读 )   评论数(:1)
评论】 【收藏】
评论:共1条
代码最好使用"插入代码"功能,这样体验效果更好一些
评论人: lengyu     评论时间: 2008-04-05 11:55:13

发表评论:
发表人:
评论: 
验证码:
请输入前面图中的四位验证码,字母不区分大小写
  
 
关于我们 | 诚聘英才 | 联系我们 | 广告业务 | 网站地图 | 法律声明

EasyJF开源团队版权所有  建议使用1024*768分辨率