首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

浅谈Acegi配备

2012-08-24 
浅谈Acegi配置Acegi Security System 是一种功能强大并易于使用的替代性方案,使您不必再为 Java 企业应用

浅谈Acegi配置

Acegi Security System 是一种功能强大并易于使用的替代性方案,使您不必再为 Java 企业应用程序编写大量的安全代码。虽然它专门针对使用 Spring 框架编写的应用程序,但是任何类型的 Java 应用程序都没有理由不去使用 Acegi。

本文的主要目的是希望能够说明如何在基于Spring构架的Web应用中使用Acegi,而不是详细介绍其中的每个接口、每个类。注意,即使对已经存在的Spring应用,通过下面介绍的步骤,也可以马上享受到Acegi提供的认证和授权。?

?

Acegi Security System 使用安全过滤器来提供企业应用程序的身份验证和授权服务。该框架提供了不同类型的过滤器,可以根据应用程序的需求进行配置。您将在本文后面了解到?安全过滤器的不同类型?;现在,只需注意可以为如下任务配置 Acegi 安全过滤器:

  1. 在访问一个安全资源之前提示用户登录。

  2. 通过检查安全标记(如密码),对用户进行身份验证。

  3. 检查经过身份验证的用户是否具有访问某个安全资源的特权。

  4. 将成功进行身份验证和授权的用户重定向到所请求的安全资源。

  5. 对不具备访问安全资源特权的用户显示 Access Denied 页面。

  6. 在服务器上记录成功进行身份验证的用户,并在用户的客户机上设置安全 cookie。使用该 cookie 执行下一次身份验证,而无需要求用户登录。

  7. 将身份验证信息存储在服务器端的会话对象中,从而安全地进行对资源的后续请求。

  8. 在服务器端对象中构建并保存安全信息的缓存,从而优化性能。

  9. 当用户退出时,删除为用户安全会话而保存的服务器端对象。

  10. 与大量后端数据存储服务(如目录服务或关系数据库)进行通信,这些服务用于存储用户的安全信息和 ECM 的访问控制策略。

正如这个列表显示的那样,Acegi 的安全过滤器允许您执行保护企业应用程序所需的几乎任何事情。

?

?

[基础工作]?
在你的Web应用的lib中添加Acegi下载包中的acegi-security.jar

?

[web.xml]

在web.xml配置

Xml代码??浅谈Acegi配备
  • <filter>??
  • ????????<filter-name>Acegi?Filter?Chain?Proxy</filter-name>??
  • ????????<filter-class>??
  • ????????????org.acegisecurity.util.FilterToBeanProxy??
  • ????????</filter-class>??
  • ????????<init-param>??
  • ????????????<param-name>targetClass</param-name>??
  • ????????????<param-value>??
  • ????????????????org.acegisecurity.util.FilterChainProxy??
  • ????????????</param-value>??
  • ????????</init-param>??
  • ????</filter>??

    ?

    <filter-mapping>限定了FilterToBeanProxy?的URL匹配模式?,

    Xml代码??浅谈Acegi配备
  • <filter-mapping>??
  • ????????<filter-name>Acegi?Filter?Chain?Proxy</filter-name>??
  • ????????<url-pattern>/*</url-pattern>??
  • ????</filter-mapping>??

    ?

    <listener>的HttpSessionEventPublisher?用于发布HttpSessionApplicationEvents?和HttpSessionDestroyedEvent?事件给spring的applicationcontext?。

    ?

    Xml代码??浅谈Acegi配备
  • <listener>??
  • ????????<listener-class>??
  • ????????????org.acegisecurity.ui.session.HttpSessionEventPublisher??
  • ????????</listener-class>??
  • ????</listener>??

    ?

    [applicationContext-acegi-security.xml]

    ?

    ?applicationContext-acegi-security.xml文件配置

    ?

    FilterChainProxy?会按顺序来调用这些filter,使这些filter能享用Spring ioc的功能?, CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义了url比较前先转为小写, PATTERN_TYPE_APACHE_ANT定义了使用Apache ant的匹配模式

    Xml代码??浅谈Acegi配备
  • <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,??
  • ??????????????basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,??
  • ????????????switchUserProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor??
  • ????????</value>??
  • ?????</property>??
  • ???</bean>??

    ?

    定义数据源为调用tomcat容器数据源 登入验证时需要获取数据源连接数据库

    Xml代码??浅谈Acegi配备
  • <bean?id="dataSource"?class="org.springframework.jndi.JndiObjectFactoryBean">??
  • ????<property?name="jndiName"><value>java:/comp/env/jdbc/test</value></property>??
  • </bean>??

    ?

    认证管理 ,从数据库中读取用户信息验证身份

    Xml代码??浅谈Acegi配备
  • <bean?id="authenticationManager"?class="org.acegisecurity.providers.ProviderManager">??
  • ???<property?name="providers">??
  • ??????<list>??
  • ?????????<ref?local="daoAuthenticationProvider"/>??
  • ??????</list>??
  • ???</property>??
  • </bean>??

    ?

    ?

    ?

    ?

    daoAuthenticationProvider?
      进行简单的基于数据库的身份验证。DaoAuthenticationProvider?获取数据库中的账号密码并进行匹配,若成功则在通过用户身份的同时返回一个包含授权信息的Authentication对象?,否则身份验证失败,抛出一个AuthenticatiionException?。

    Xml代码??浅谈Acegi配备
  • ?<bean?id="daoAuthenticationProvider"?class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">??
  • ??????<property?name="userDetailsService"><ref?local="jdbcDaoImpl"/></property>??
  • ??????<property?name="passwordEncoder"><ref?local="passwordEncoder"/></property>??
  • ??????<property?name="userCache"><ref?local="userCache"/></property>??
  • ?</bean>??

    ?

    jdbcDaoImpl

    用于在数据中获取用户信息

    Xml代码??浅谈Acegi配备
  • <bean?id="jdbcDaoImpl"?class="com.milesup.acegi.userdetails.jdbc.JdbcDaoImpl">??
  • ??????<property?name="dataSource"><ref?bean="dataSource"/></property>??
  • ??????<property?name="rolePrefix"><value>ROLE_</value></property>??
  • ???</bean>??

    ?

    passwordEncoder

    ? 使用加密器对用户输入的明文进行加密。Acegi提供了三种加密器:

    Xml代码??浅谈Acegi配备
  • 1?:???PlaintextPasswordEncoder—默认,不加密,返回明文.??
  • 2?:???ShaPasswordEncoder—哈希算法(SHA)加密??
  • 3?:???Md5PasswordEncoder—消息摘要(MD5)加密???

    使用加密器对用户输入的明文进行加密 为MD5加密方式

    Xml代码??浅谈Acegi配备
  • <bean?id="passwordEncoder"?class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>??

    ?

    缓存用户和资源相对应的权限信息。每当请求一个受保护资源时,daoAuthenticationProvider?就会被调用以获取用户授权信息?。如果每次都从数据库获取的话,那代价很高,对于不常改变的用户和资源信息来说,最好是把相关授权信息缓存起来。
    userCache提供了两种实现:?NullUserCache?和EhCacheBasedUserCache?,?NullUserCache?实际上就是不进行任何缓存,EhCacheBasedUserCache?是使用Ehcache来实现缓功能。

    Xml代码??浅谈Acegi配备
  • <!--?缓存管理?-->??
  • ???<bean?id="cacheManager"?class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>??
  • ????<!--?缓存用户和资源相对应的权限信息?-->??
  • ???<bean?id="userCacheBackend"?class="org.springframework.cache.ehcache.EhCacheFactoryBean">??
  • ??????<property?name="cacheManager">??
  • ?????????<ref?local="cacheManager"/>??
  • ??????</property>??
  • ??????<property?name="cacheName">??
  • ?????????<value>userCache</value>??
  • ??????</property>??
  • ???</bean>??
  • ?????
  • ???<bean?id="userCache"?class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">??
  • ??????<property?name="cache"><ref?local="userCacheBackend"/></property>??
  • ???</bean>??

    ?

    该过滤器用来处理在系统认证授权过程中抛出的异常

    Xml代码??浅谈Acegi配备
  • <bean?id="exceptionTranslationFilter"?class="org.acegisecurity.ui.ExceptionTranslationFilter">??
  • ?????<property?name="authenticationEntryPoint"><ref?local="authenticationProcessingFilterEntryPoint"/></property>??
  • ??</bean>??

    ?

    ?

    一个没有进行身份验证的用户试图访问受保护的资源验证是否授权? Exception Translation Filter(ETF)

    Xml代码??浅谈Acegi配备
  • <bean?id="authenticationProcessingFilterEntryPoint"?class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">??
  • ??????<property?name="loginFormUrl"><value>/login.jsp</value></property>??
  • ??????<property?name="forceHttps"><value>false</value></property>??
  • ???</bean>??

    ?

    登入验证

    成功进入main.jsp页面? ,失败跳转到/login.jsp?login_error=1? ,登入url为 /j_acegi_security_check, Authentication Processing Filter(APF)

    ??????? authenticationFailureUrl?定义登陆失败时转向的页面
    ?????????defaultTargetUrl?定义登陆成功时转向的页面
    ?????????filterProcessesUrl?定义登陆请求的页面
    ?????????rememberMeServices?用于在验证成功后添加cookie信息

    Xml代码??浅谈Acegi配备
  • <bean?id="authenticationProcessingFilter"?class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">??
  • ??????<property?name="authenticationManager"><ref?bean="authenticationManager"/></property>??
  • ??????<property?name="authenticationFailureUrl"><value>/login.jsp?login_error=1</value></property>??
  • ??????<property?name="defaultTargetUrl"><value>/main.jsp</value></property>??
  • ??????<property?name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>??
  • ?????<property?name="rememberMeServices"><ref?local="rememberMeServices"/></property>??
  • ?</bean>??

    ?

    ?

    Xml代码??浅谈Acegi配备
  • 用于处理HTTP头的认证信息,如从<span?style="color:?#0000ff;"><strong>Spring远程协议</strong>??
  • </span>??
  • (如Hessian和Burlap)或<span?style="color:?#0000ff;"><strong>普通的浏览器如IE,Navigator的HTTP头</strong>??
  • </span>??
  • 中获取用户??
  • 信息,将他们转交给通过<span?style="text-decoration:?underline;">authenticationManager</span>??
  • 属性装配的认证管理器。如果认证成功,会<span?style="text-decoration:?underline;">将一个Authentication对象放到会话中</span>??
  • ??
  • ,否则,如果认证失败,会将控制<span?style="text-decoration:?underline;">转交给认证入口点</span>??
  • (通过authenticationEntryPoint属性装配)??
  • <!--?用于处理HTTP头的认证信息?-->??
  • ???<bean?id="basicProcessingFilter"?class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">??
  • ??????<property?name="authenticationManager"><ref?local="authenticationManager"/></property>??
  • ??????<property?name="authenticationEntryPoint"><ref?local="basicProcessingFilterEntryPoint"/></property>??
  • ???</bean>??
  • ?????
  • ???<!--?通过向浏览器发送一个HTTP401(未授权)消息,提示用户登录?-->??
  • ???<bean?id="basicProcessingFilterEntryPoint"?class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">??
  • ??????<property?name="realmName"><value>Milesup?Realm</value></property>??
  • ???</bean>???

    注销 退出验证 跳转到/login.jsp

    Xml代码??浅谈Acegi配备
  • <bean?id="logoutFilter"?class="org.acegisecurity.ui.logout.LogoutFilter">??
  • ??????<constructor-arg?value="/login.jsp"/><constructor-arg>??
  • ?????????<list>??
  • ??????????????<bean?class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>??
  • ?????????</list>??
  • ??????</constructor-arg>??
  • ???</bean>??

    ?

    经过投票?机制来决定是否可以访问某一资源(URL?或方法?)。allowIfAllAbstainDecisions为false时如果有一个或以上的decisionVoters投票通过,则授权通过。可选的决策机制有ConsensusBased和UnanimousBased

    ?

    roleVoter?
      必须是以rolePrefix设定的value开头的权限才能进行投票,如 ROLE_

    Xml代码??浅谈Acegi配备
  • <bean?id="roleVoter"?class="org.acegisecurity.vote.RoleVoter">??
  • ??????<property?name="rolePrefix">??
  • ?????????<value>ROLE_</value>??
  • ??????</property>??
  • ???</bean>??
  • ??
  • ??<!--?组件管理授权过程??决策管理器-->??
  • ???<bean?id="httpRequestAccessDecisionManager"?class="org.acegisecurity.vote.AffirmativeBased">??
  • ??????<property?name="allowIfAllAbstainDecisions"><value>false</value></property>??
  • ??????<property?name="decisionVoters">??
  • ?????????<list>??
  • ????????????<ref?bean="roleVoter"/>??
  • ?????????</list>??
  • ??????</property>??
  • ???</bean>???

    ?

    过滤器安全拦截器? 是否认证,是否有权限访问受保护的资源

     在执行转向url前检查objectDefinitionSource?中设定的用户权限信息。首先,objectDefinitionSource?中定义了访问URL需要的属性信息(这里的属性信息仅仅是标志,告诉accessDecisionManager?要用哪些voter来投票)。然后,authenticationManager?掉用自己的provider来对用户的认证信息进行校验。最后,有投票者根据用户持有认证和访问url需要的属性,调用自己的voter来投票,决定是否允许访问。

    Xml代码??浅谈Acegi配备
  • <bean?id="filterInvocationInterceptor"?class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">??
  • ??????<property?name="authenticationManager"><ref?bean="authenticationManager"/></property>??
  • ??????<property?name="accessDecisionManager"><ref?local="httpRequestAccessDecisionManager"/></property>??
  • ??????<property?name="objectDefinitionSource">??
  • ?????????<value>??
  • ????????????PATTERN_TYPE_APACHE_ANT??
  • ????????????/user.jsp=ROLE_ADMIN??
  • ????????????/admin=ROLE_ADMIN??
  • ?????????</value>??
  • ??????</property>??
  • ???</bean>???

    ?

    [login.jsp]

    ?

    Html代码??浅谈Acegi配备
  • <form?action="/j_acegi_security_check"?method="post"?>??
  • ????<table>??
  • ??????????????????<tr>??
  • ????????????????????<td?width="140"?height="22"?align="right">用户名</td>??
  • ????????????????????<td?width="47%"?align="left"><input?value="${lastUserName}"?name="j_username"?type="text"?class="inputstyle"?id="j_username"></td>??
  • ????????????????????<td?align="left"?nowrap><div?class="loginmeon">?</div></td>??
  • ??????????????????</tr>??
  • ??????????????????<tr>??
  • ????????????????????<td?width="140"?height="22"?align="right">密 码</td>??
  • ????????????????????<td?width="47%"?align="left"><input?name="j_password"?type="password"?class="inputstyle"?id="j_password"?size="21"></td>??
  • ??????????????????</tr>??
  • ?<tr>??
  • ????????????????????<td?height="60"?colspan="3"?align="center"?valign="middle">??
  • ?????????????????<input?type="submit"?name="imageField2"?value="登入"></td>??
  • ??????????????????</tr>??
  • ????????????????</table>??
  • ????????????????</td>??
  • ??????????????</tr>??
  • ???????????</table>??
  • ?????????</td>??
  • ??????</tr>??
  • ????</table>??
  • ?</form>??????

    [JdbcDaoImpl.java]

    ?

    Java代码??浅谈Acegi配备
  • public?class?JdbcDaoImpl?extends?org.acegisecurity.userdetails.jdbc.JdbcDaoImpl?{??
  • ??
  • ????private?String?anonymousRoleName?=?"ROLE_ANONYMOUS";??
  • ??
  • ????private?Log?logger?=?LogFactory.getLog(JdbcDaoImpl.class);??
  • ??
  • ????private?PreparedStatement?userPstmt;??
  • ??
  • ????private?PreparedStatement?rolePstmt;??
  • ??
  • ????public?UserDetails?loadUserByUsername(String?userName)??
  • ????????????throws?UsernameNotFoundException,?DataAccessException?{??
  • ????????UserDetails?user?=?findUserByName(userName);??
  • ??
  • ????????if?(user?==?null)?{??
  • ????????????throw?new?UsernameNotFoundException("User?not?found");??
  • ????????}??
  • ??
  • ????????return?user;??
  • ????}??
  • ??
  • ????private?UserDetails?findUserByName(String?userName)?{??
  • ????????Connection?connection?=?null;??
  • ????????ResultSet?rsUser?=?null;??
  • ????????ResultSet?rsRole?=?null;??
  • ????????UserDetails?user?=?null;??
  • ????????String?logonName?=?null;??
  • ????????String?password?=?null;??
  • ????????String?roleName?=?null;??
  • ????????int?status?=?-1;??
  • ????????boolean?enabled?=?false;??
  • ????????Vector?roles?=?null;??
  • ????????GrantedAuthority[]?rolesArray?=?null;??
  • ??
  • ????????try?{??
  • ????????????connection?=?getDataSource().getConnection();??
  • ????????????userPstmt?=?connection??
  • ????????????????????.prepareStatement("select?*?from?users?where?user_NAME=?");??
  • ????????????userPstmt.setString(1,?userName);??
  • ????????????rsUser?=?userPstmt.executeQuery();??
  • ????????????if?(rsUser.next())?{??
  • ????????????????logonName?=?rsUser.getString("USER_NAME");??
  • ????????????????password?=?rsUser.getString("PASSWORD");??
  • ????????????????status?=?rsUser.getInt("STATUS");??
  • ????????????????if?(status?==?1)??
  • ????????????????????enabled?=?true;??
  • ????????????}?else?{??
  • ????????????????return?null;??
  • ????????????}??
  • ????????????rolePstmt?=?connection??
  • ????????????????????.prepareStatement("SELECT?ROLE.NAME?Role?FROM?ROLE,??users_ROLES,??users?WHERE?ROLE.ID=?user_ROLES.FK_ROLES??and?users.user_NAME=?");??
  • ????????????rolePstmt.setString(1,?userName);??
  • ????????????rsRole?=?rolePstmt.executeQuery();??
  • ????????????roles?=?new?Vector();??
  • ????????????while?(rsRole.next())?{??
  • ????????????????roleName?=?getRolePrefix()?+?rsRole.getString("Role");??
  • ????????????????roles.add(new?GrantedAuthorityImpl(roleName));??
  • ????????????}??
  • ????????????rolesArray?=?new?GrantedAuthority[roles.size()?+?1];??
  • ????????????int?index?=?0;??
  • ????????????for?(index?=?0;?index?<?roles.size();?index++)??
  • ????????????????rolesArray[index]?=?(GrantedAuthority)?roles.get(index);??
  • ????????????rolesArray[index]?=?new?GrantedAuthorityImpl(anonymousRoleName);??
  • ????????????user?=?new?User(logonName,?password,?enabled,?true,?true,?true,??
  • ????????????????????rolesArray);??
  • ????????}?catch?(SQLException?e)?{??
  • ????????????logger.fatal("",?e);??
  • ????????}?finally?{??
  • ????????????try?{??
  • ????????????????rsRole.close();??
  • ????????????????rsUser.close();??
  • ????????????????userPstmt.close();??
  • ????????????????rolePstmt.close();??
  • ????????????????connection.close();??
  • ????????????}?catch?(SQLException?sqlx)?{??
  • ????????????????logger.fatal("",?sqlx);??
  • ????????????}?catch?(NullPointerException?x)?{??
  • ????????????????logger.fatal("",?x);??
  • ????????????}??
  • ????????}??
  • ????????return?user;??
  • ????}??
  • ??
  • }???

  • 热点排行