`
zhouxingfu520
  • 浏览: 421522 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Acegi 使用笔记

阅读更多

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

<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匹配模式 ,

<filter-mapping>
		<filter-name>Acegi Filter Chain Proxy</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 

<listener>的HttpSessionEventPublisher 用于发布HttpSessionApplicationEventsHttpSessionDestroyedEvent 事件给spring的applicationcontext

<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的匹配模式

	<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容器数据源 登入验证时需要获取数据源连接数据库

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName"><value>java:/comp/env/jdbc/test</value></property>
    </bean>

 

Acegi提供了不同的AuthenticationProvider的实现,如:

DaoAuthenticationProvider 从数据库中读取用户信息验证身份
AnonymousAuthenticationProvider 匿名用户身份认证
RememberMeAuthenticationProvider 已存cookie中的用户信息身份认证
AuthByAdapterProvider 使用容器的适配器验证身份
CasAuthenticationProvider 根据Yale中心认证服务验证身份, 用于实现单点登陆
JaasAuthenticationProvider 从JASS登陆配置中获取用户信息验证身份
RemoteAuthenticationProvider 根据远程服务验证用户身份
RunAsImplAuthenticationProvider 对身份已被管理器替换的用户进行验证
X509AuthenticationProvider 从X509认证中获取用户信息验证身份
TestingAuthenticationProvider 单元测试时使用  

 

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

   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers">
         <list>
            <ref local="daoAuthenticationProvider"/>
         </list>
      </property>
   </bean>

 

 

 

 

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

 <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

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

<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提供了三种加密器:

1 :   PlaintextPasswordEncoder—默认,不加密,返回明文.
2 :   ShaPasswordEncoder—哈希算法(SHA)加密
3 :   Md5PasswordEncoder—消息摘要(MD5)加密
 

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

<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>

 

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

<!-- 缓存管理 -->
   <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>

 

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

 <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
      <property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>
   </bean>

 

 

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

<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信息

<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>

 

用于处理HTTP头的认证信息,如从Spring远程协议    (如Hessian和Burlap)或普通的浏览器如IE,Navigator的HTTP头
    中获取用户    信息,将他们转交给通过authenticationManager    属性装配的认证管理器。如果认证成功,会将一个Authentication对象放到会话中    ,否则,如果认证失败,会将控制转交给认证入口点 (通过                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

<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_

<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来投票,决定是否允许访问。

<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]

 

<form action="/j_acegi_security_check" method="post" >
    <table>
                  <tr>
                    <td width="140" height="22" align="right">用户名</td>
                    <td width="47%" align="left"><input 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]

 

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 {
				//关闭数据库连接的程序
			} catch (SQLException sqlx) {
				logger.fatal("", sqlx);
			} catch (NullPointerException x) {
				logger.fatal("", x);
			}
		}
		return user;
	}

}
分享到:
评论

相关推荐

    acegi——笔记学习

    在Acegi笔记中,你可能会发现以下内容: - 如何配置Acegi以启用安全保护,包括设置安全拦截器和定义安全过滤器链。 - 用户认证的实现,包括定义`UserDetailsService`来获取用户信息,以及配置不同的认证提供者。 - ...

    Acegi学习笔记(JAVA系统安全编程时用到)

    在开始使用 Acegi 之前,你需要从 Acegi 的官方网站下载对应的程序库,例如版本为 1.0.3。这个版本中包含了与 Spring 1.2.8 版本兼容的 Acegi 安全库。Acegi 的依赖关系可以通过依赖注入(IoC)容器来管理,这里推荐...

    Acegi学习笔记--Acegi详解实战Acegi实例

    Acegi是Spring框架早期的一个安全模块,主要用于身份验证和授权管理。在2009年,Acegi被Spring Security所吸收,成为其前身,因此理解Acegi有助于我们深入理解Spring Security的安全机制。以下是对Acegi的详细介绍和...

    Acegi身份认证框架的使用笔记

    一个使用Acegi身份认证框架的笔记 可以节省你的时间 方便快速学会使用

    acegi学习笔记

    ### Acegi学习笔记详解 #### 一、Acegi Security概览 **Acegi Security**,作为Spring Security的前身,是一个深度融入Spring Framework的安全框架,它为开发者提供了一套全面的安全解决方案,尤其在Web应用程序中...

    acegi权限控制学习笔记

    Acegi权限控制学习笔记 Acegi安全框架是Spring Security的前身,它提供了一种强大的、灵活的、基于组件的安全解决方案,用于实现企业级应用的安全控制。在这个学习笔记中,我们将探讨两个关键点:身份认证成功后的...

    基于java的ACEGI

    在《实战Acegi:使用Acegi作为基于Spring框架的WEB应用的安全框架.pdf》中,可能会详细讲解如何配置和使用Acegi。以下是一些关键步骤: 1. **添加依赖**:首先,在项目中引入Acegi的依赖库,通常是通过Maven或...

    acegi学习

    "Acegi使用.pdf"文档应该是一个详细的使用指南,提供了如何在项目中集成和配置Acegi的步骤。它可能包括设置安全配置文件、创建用户存储(如内存、JDBC或LDAP)、定义安全策略,以及如何处理未授权和未认证的异常。...

    CAS 单点登录安装笔记3 -- 与acegi集成

    acegi-context配置文件 博文链接:https://lib.iteye.com/blog/165980

    acegi资料大全-全集

    `Acegi学习小结-Spring-Java -JavaEye做最棒的软件开发交流社区.mht`可能是一个社区成员的学习笔记,汇总了他在使用Acegi过程中遇到的问题和解决办法,这类资料往往能提供实战中的宝贵经验。 `学习Acegi-认证...

    Acegi 概述

    Acegi是Spring Security的前身,它是一个非常强大的Java安全框架,用于解决企业级...如果你想要了解更多关于Acegi的细节,可以参考提供的博客链接或阅读"Acegi笔记.doc"文档,其中可能包含了更多实践案例和详细教程。

    良葛格java学习笔记

    常見程式演算,電腦圖學入門,設計模式,C 語言,GTK,C++,Qt3,Qt4,,Java (上),Java (下),JSP/Servlet,JSF,Ajax,JUnit,Struts,Spring,Hibernate,Acegi

    AppFuse学习笔记

    它集成了多种流行的技术,如 Ant 构建工具、Tapestry 表现层框架、Hibernate 持久层框架、Spring 事务管理和服务层以及 Acegi 安全管理。本文将详细介绍如何使用 AppFuse 来构建一个 J2EE 应用,同时提供了一个简单...

    appfuse 学习笔记

    此外,安全(SECURITY)是AppFuse关注的另一重要领域,它支持Spring Security(原Acegi Security)来处理用户认证和授权。 总的来说,AppFuse是一个强大的开发工具,它通过集成多种成熟技术,为开发者提供了一个...

    Spring源代码解析.rar

    Spring源代码解析1:IOC容器.doc Spring源代码解析2:IoC容器在Web容器中的启动.doc Spring源代码解析3:Spring JDBC .doc Spring源代码解析4:Spring MVC .doc ...Spring源代码解析10:Spring Acegi框架授权的实现.doc

    xdoclet_appfuse打包

    6. "Acegi+hibernate 动态实现基于角色的权限管理.doc":Acegi(现为Spring Security的一部分)是一个安全框架,配合Hibernate进行动态角色权限管理,这个文档可能会阐述如何设置和使用这种系统。 7. "appfuse开发...

    java文集

    ext学习笔记一 小试iBatis RIA(Rich Internet Application)的现状和未来 Java应用中域名解析不过期的解决方法 Java编程那些事儿45—数组使用示例1 一步步熟悉OFBiz 用Java做客户端调用.NET写...

Global site tag (gtag.js) - Google Analytics