- 浏览: 158855 次
- 性别:
- 来自: 奥克兰
文章分类
最新评论
-
u012625419:
...
CXF之用spring配置服务端和客户端实例(转) -
bambooshangye:
CXF之用spring配置服务端和客户端实例(转) -
最佳蜗牛:
写的很好,谢谢!
tomcat下的server.xml文件和context.xml (转) -
mohaowen1989:
亲 有中文版的么?在grails基础上的spring-secu ...
Simplified Spring Security with Grails(转) -
douhongyang:
挺好,,思路很清晰,
spring security详解教程 (转)
身份认证管理
使用 Acegi 保护应用程序的第一步是根据用户提供的认证信息进行身份认证,以确定用户的身份获取对应的权限信息准备好 Authentication 。通过认证的 Authentication 拥有权限信息,它是 Acegi 进行后续安全对象访问安全控制的依据。
基于内存存储用户信息的身份认证
applicationContext-acegi-plugin.xml
- < bean id = "filterChainProxy" class = "org.acegisecurity.util.FilterChainProxy" >
- < property name = "filterInvocationDefinitionSource" >
- < value >
- CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
- PATTERN_TYPE_APACHE_ANT
- /**=authenticationProcessingFilter
- </ value >
- </ property >
- </ bean >
- < bean id = " authenticationProcessingFilter " class = "org.acegisecurity.util.webapp.AuthenticationProcessingFilter" >
- < property name = "filterProcessesUrl" value = "/j_acegi_security_check" />
- < property name = "defaultTargetUrl" value = "/main.jsp" />
- < property name = "authenticationFailureUrl" value = "/index.jsp?login_error=1" />
- </ bean >
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=authenticationProcessingFilter </value> </property> </bean> <bean id=" authenticationProcessingFilter " class="org.acegisecurity.util.webapp.AuthenticationProcessingFilter"> <property name="filterProcessesUrl" value="/j_acegi_security_check"/> <property name="defaultTargetUrl" value="/main.jsp"/> <property name="authenticationFailureUrl" value="/index.jsp?login_error=1"/> </bean>
添加登录页面index.jsp:
- < %@ taglib prefix =”c” uri = http ://java.sun.com/jsp/jstl/core%” >
- < form name = "form1" method = "post" action = "<c:url value=" /j_acegi_security_check" /> " >
- 用户名:< input type = "text" name = "j_username" /> < br />
- 密 码:< input type = "password" name = "j_password" /> < br />
- < input type = "submit" value = "登录" />
- </ form >
<%@ taglib prefix=”c” uri=http://java.sun.com/jsp/jstl/core%”> <form name="form1" method="post" action="<c:url value="/j_acegi_security_check"/>"> 用户名:<input type="text" name="j_username"/><br/> 密 码:<input type="password" name="j_password"/><br/> <input type="submit" value="登录"/> </form>
applicationContext-acegi-plugin.xml : 认证管理器的配置
- < bean id = "authenticationProcessingFilter"
- class = "org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" >
- <!—处理过滤器的URL -->
- < property name = "filterProcessesUrl" value = "/j_acegi_security_check" />
- <!--认证成功后转向的URL -->
- < property name = "defaultTargetUrl" value = "/main.jsp" />
- <!--认证失败后转向的URL -->
- < property name = "authenticationFailureUrl" value = "/index.jsp?login_error=1" />
- <!--注入认证管理器 -->
- < property name = "authenticationManager" ref = "authenticationManager" />
- </ bean >
- < bean id = "authenticationManager"
- class = "org.acegisecurity.providers.ProviderManager" >
- < property name = "providers" >
- < list >
- <!--使用基于DAO的认证提供者提供认证服务-->
- < ref local = "daoAuthenticationProvider" />
- </ list >
- </ property >
- </ bean >
- < bean id = "daoAuthenticationProvider"
- class = "org.acegisecurity.providers.dao.DaoAuthenticationProvider" >
- <!--注入根据用户名获取系统中真实UserDetails对象的服务类 -->
- < property name = "userDetailsService" ref = "userDetailsService" />
- </ bean >
- < bean id = "userDetailsService"
- class = "org.acegisecurity.userdetails.jdbc.InMemoryDaoImpl" >
- < property name = "userMap" >
- < value >
- John = john ,PRIV_COMMON,PRIV_1
- Tom = tom ,PRIV_COMMON,PRIV_1,PRIV_2
- Peter = peter ,disabled,PRIV_COMMON,PRIV_1
- </ value >
- </ property >
- </ bean >
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <!—处理过滤器的URL --> <property name="filterProcessesUrl" value="/j_acegi_security_check"/> <!--认证成功后转向的URL --> <property name="defaultTargetUrl" value="/main.jsp"/> <!--认证失败后转向的URL --> <property name="authenticationFailureUrl" value="/index.jsp?login_error=1" /> <!--注入认证管理器 --> <property name="authenticationManager" ref="authenticationManager"/> </bean> <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <!--使用基于DAO的认证提供者提供认证服务--> <ref local="daoAuthenticationProvider" /> </list> </property> </bean> <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <!--注入根据用户名获取系统中真实UserDetails对象的服务类 --> <property name="userDetailsService" ref="userDetailsService" /> </bean> <bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.InMemoryDaoImpl"> <property name="userMap"> <value> John=john,PRIV_COMMON,PRIV_1 Tom=tom,PRIV_COMMON,PRIV_1,PRIV_2 Peter=peter,disabled,PRIV_COMMON,PRIV_1 </value> </property> </bean>
Acegi 提供了不同的 AuthenticationProvider 的实现 , 如:
- DaoAuthenticationProvider 从 Dao 类负责读取用户信息验证身份
- AnonymousAuthenticationProvider 匿名用户身份认证
- RememberMeAuthenticationProvider 已存 cookie 中的用户信息身份认证
- AuthByAdapterProvider 使用容器的适配器验证身份
- CasAuthenticationProvider 根据 Yale 中心认证服务验证身份 , 用于实现单点登陆
- JaasAuthenticationProvider 从 JASS 登陆配置中获取用户信息验证身份
- RemoteAuthenticationProvider 根据远程服务验证用户身份
- RunAsImplAuthenticationProvider 对身份已被管理器替换的用户进行验证
- X509AuthenticationProvider 从 X509 认证中获取用户信息验证身份
- TestingAuthenticationProvider 单元测试时使用
DaoAuthenticationProvider 通过 UserDetailsService 完成 UserDetails 的获取工作,根据存储用户信息媒介的不同, Acegi 提供了两个 UserDetailsService 的实现类:
- InMemoryDaoImpl :该实现类负责从内在中获取用户的信息
- JdbcDaoImpl: 该实现类从数据库中获取用户的信息
如果用户数比较多,在Spring中直接进行配置未免不太雅观,这时,可以将用户信息转移到一个属性文件中,并通过userProperties进行加载,则需对userDetailsService稍做修改
- < bean id = "userDetailsService"
- class = "org.acegisecurity.userdetails.jdbc.InMemoryDaoImpl" >
- < property name = "userProperties" >
- < bean class = "org.springframework.beans.factory.config.PropertiesFactoryBean" >
- < property name = "location" value = "/WEB-INF/users.properties" />
- </ bean >
- </ property >
- </ bean >
<bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.InMemoryDaoImpl"> <property name="userProperties"> <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location" value="/WEB-INF/users.properties"/> </bean> </property> </bean>
基于数据库存储用户信息的认证
applicationContext-acegi-plugin.xml :
- < bean id = "userDetailsService"
- class = "org.acegisecurity.userdetails.jdbc.JdbcDaoImpl" >
- <!—数据源-->
- < property name = "dataSource" ref = "dataSource" />
- < property name = "usersByUsernameQuery" >
- < value >
- <!--根据用户名查询用户的SQL语句-->
- SELECT username,password,status FROM t_user WHERE username = ?
- </ value >
- </ property >
- < property name = "authoritiesByUsernameQuery" >
- < value >
- <!--根据用户名查询用户权限记录的SQL语句-->
- SELECT u.username,p.priv_name FROM t_user u,t_user_priv
- p WHERE u.user_id = p .user_id AND u.username = ?
- </ value >
- </ property >
- </ bean >
<bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"> <!—数据源--> <property name="dataSource" ref="dataSource" /> <property name="usersByUsernameQuery"> <value> <!--根据用户名查询用户的SQL语句--> SELECT username,password,status FROM t_user WHERE username = ? </value> </property> <property name="authoritiesByUsernameQuery"> <value> <!--根据用户名查询用户权限记录的SQL语句--> SELECT u.username,p.priv_name FROM t_user u,t_user_priv p WHERE u.user_id =p.user_id AND u.username = ? </value> </property> </bean>
应该说 JdbcDaoImpl 还不是非常实用的 UserDetailsService 实现类,因为用户对象除包含用户名 / 密码、是否激活、权限等信息外,还经常需要包含一些诸如 email 、 telephone 等到业务相关的信息,所以我们往往需要通过实现 UserDetailsService 接口提供自己的的实现类来完成这些工作。
具体可以参照: Spring Security 2 配置精讲 : http://www.iteye.com/topic/319965
密码加密问题
在获取 UserDetails 后, DaoAuthenticationProvider 要做的工作是比较 Authentication 和 UserDetails 的匹配关系并给出认证成功或失败的认证结果。下面是两个关键接口:
- org.acegisecurity.providers.encoding.PasswordEncoder
- org.acegisecurity.providers.dao.SaltSource
PasswordEncoder 完成两件工作:
- 对明文的密码( Authentication#getCredentials() )进行编码
- 对处于非对称状态(一个是加密的,另一个是明文的)
PasswordEncoder 进行密码比较时,需要使用到一个 SaltSource, 它代表一个“加密盐”,对用户提供的密码进行加密时采用的加密盐必须和系统中保存的用户加密密码所采用的加密盐相同。它有两个接口方法:
- String encodePassword(String rawPass, Object salt) //对原始未加密的密码通过一定的算法进行加密运算
- Boolean isPasswordValid(String encPass, String rawPass, Object salt) //通过算法判断待认证用户所提供的密码是否有效
String encodePassword(String rawPass, Object salt) //对原始未加密的密码通过一定的算法进行加密运算 Boolean isPasswordValid(String encPass, String rawPass, Object salt) //通过算法判断待认证用户所提供的密码是否有效
几种常的PasswordEncoder实现类, 密码编码器
- Md5PasswordEncoder 使用 MD5 算法加密
- ShaPasswordEncoder 使用 SHA 算法加密
- LdapShaPasswordEncoder 使用 LDAP SHA 和平 SSHA 算法加密
- PlaintextPasswordEncoder 不加密
SaltSource 接口公有一个 Object gestalt(UserDetails user) 方法,它有两个实现类:
org.acegisecurity.providers.dao.salt.ReflectionSaltSource : 允许用户在 UserDetails 中提供一个代表加密盐的属性
org.acegisecurity.providers.dao.salt.SystemWideSaltSource :该实现类不允许不同用户采用各自的加密盐,它采用全局范围统一的加密盐。
applicationContext-acegi-plugin.xml :
- < bean id = "daoAuthenticationProvider"
- class = "org.acegisecurity.providers.dao.DaoAuthenticationProvider" >
- <!--注入根据用户名获取系统中真实UserDetails对象的服务类 -->
- < property name = "userDetailsService" ref = "userDetailsService" />
- < property name = "passwordEncoder" >
- < bean class = "org.acegisecurity.providers.encoding.Md5PasswordEncoder" />
- </ property >
- < property name = "saltSource" >
- < bean class = "org.acegisecurity.providers.dao.salt.SystemWideSaltSource" >
- < property name = "systemWideSalt" value = "ccd1010" />
- </ bean >
- </ property >
- </ bean >
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <!--注入根据用户名获取系统中真实UserDetails对象的服务类 --> <property name="userDetailsService" ref="userDetailsService" /> <property name="passwordEncoder"> <bean class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/> </property> <property name="saltSource"> <bean class="org.acegisecurity.providers.dao.salt.SystemWideSaltSource"> <property name="systemWideSalt" value="ccd1010"/> </bean> </property> </bean>
成功登录系统的后置处理
一般的业务系统在用户登录成功后,需要在数据库中记录一条相应的用户登录日志。 Acegi 会产生一个 AuthenticationSuccessEvent 事件, 该事件是 org.springframework.context.ApplicationEvent 的子类,所以它是一个 Spring 容器事件。
- package com.ccd.service;
- import org.acegisecurity.Authentication;
- import org.acegisecurity.event.authentication.AuthenticationSuccessEvent;
- import org.springframework.context.ApplicationEvent;
- import org.springframework.context.ApplicationListener;
- public class LoginSuccessListener implements ApplicationListener{
- public void onApplicationEvent(ApplicationEvent event){
- if (event instanceof AuthenticationSuccessEvent){
- AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent) event;
- Authentication auth = authEvent.getAuthentication();
- String username = auth.getName();
- System.out.println(“模拟记录用户[”+username+”]成功登录日志...”);
- }
- }
- }
package com.ccd.service; import org.acegisecurity.Authentication; import org.acegisecurity.event.authentication.AuthenticationSuccessEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; public class LoginSuccessListener implements ApplicationListener{ public void onApplicationEvent(ApplicationEvent event){ if(event instanceof AuthenticationSuccessEvent){ AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent) event; Authentication auth = authEvent.getAuthentication(); String username = auth.getName(); System.out.println(“模拟记录用户[”+username+”]成功登录日志...”); } } }
接下来,在 Spring 容器中声明这个监听器,仅需要一行就可以了:
<bean class=”com.ccd.service.LoginSuccessListener”/>
在多个请求之间共享 SecurityContext
Acegi 通过 HttpSessionContextIntegrationFilter 使 SecurityContext 在 Session 级别中共享,当一个请求到达时,它尝试从 Session 中获取用户关联的 SecurityContext 并将其放入到 SecurityContextHolder 中,当请求结束时, HttpSessionContextIntegrationFilter 又将 SecurityContext 转存到 HttpSession 中。这样, Acegi 就通过 HttpSessionContextIntegrationFilter 将 SecurityContext 对象在请求级的 SecurityContextHolder 和 Session 级的 HttpSession 中摆渡,从而保证 SecurityContext 可以在多个请求之间共享。 注意, 此 filter 必须于其他 Acegi Filter 前使用 。
applicationContext-acegi-plugin.xml :
- < bean id = "filterChainProxy" class = "org.acegisecurity.util.FilterChainProxy" >
- < property name = "filterInvocationDefinitionSource" >
- < value >
- …
- /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter
- </ value >
- </ property >
- </ bean >
- <!—通过HttpSession转存SecurityContext的过滤器 -->
- < bean id = "httpSessionContextIntegrationFilter"
- class = "org.acegisecurity.context.HttpSessionContextIntegrationFilter" />
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> … /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter </value> </property> </bean> <!—通过HttpSession转存SecurityContext的过滤器 --> <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />
退出系统的后置处理
SecyrityContext 保存在 HttpSession 中,当用户退出系统时必须清除之,否同要等到 Session 过期后才会被清除,造成额外的内存消耗。 Acegi 为完成一系列由退出系统引发的操作,专门提供了一个退出过滤器: org.acegisecurity.ui.logout.LogoutFilter 。
applicationContext-acegi-plugin.xml :
- < bean id = "filterChainProxy" class = "org.acegisecurity.util.FilterChainProxy" >
- < property name = "filterInvocationDefinitionSource" >
- < value >
- …
- /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,logoutFilter
- </ value >
- </ property >
- </ bean >
- < bean id = "logoutFilter"
- class = "org.acegisecurity.ui.logout.LogoutFilter" >
- <!—退出系统前需要执行的操作 -->
- < constructor-arg >
- < list >
- < bean
- class = "org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
- </ list >
- </ constructor-arg >
- <!—退出系统后转向的URL -->
- < constructor-arg value = "/index.jsp" />
- <!—用于响应退出系统请求的URL-->
- < property name = "filterProcessesUrl" value = "/j_acegi_logout" />
- </ bean >
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> … /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,logoutFilter </value> </property> </bean> <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter"> <!—退出系统前需要执行的操作 --> <constructor-arg> <list> <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" /> </list> </constructor-arg> <!—退出系统后转向的URL --> <constructor-arg value="/index.jsp" /> <!—用于响应退出系统请求的URL--> <property name="filterProcessesUrl" value="/j_acegi_logout" /> </bean>
配置一个退出系统的操作链接
<A href= "<c:url value="/j_acegi_logout"/>"> 退出系统 </A>
实施 Remember-Me 认证
发表评论
-
Spring MVC中修改校验的异常信息
2011-04-06 13:25 1690Spring MVC中修改校验的异常信息 原文转自: ... -
Spring 3之MVC & Security简单整合开发(三)
2011-03-01 11:01 1297为了方便学习,原文转自http://sarin.iteye.c ... -
Spring 3之MVC & Security简单整合开发(二)
2011-03-01 10:59 2113为了方便学习,原文出自http://sarin.iteye.c ... -
Spring 3之MVC & Security简单整合开发(一)(转)
2011-03-01 10:58 1565为了方便学习,原文出自http://sarin.iteye.c ... -
Spring与Hibernate两种组合方式 (转)
2010-10-07 17:31 1881Spring与Hibernate大致有两种组合方式,主要区别是 ... -
Spring Security Acegi 学习之路四 (转)
2010-09-16 12:34 1685安全对象访问控制 Aceg ... -
Spring Security Acegi 学习之路二(转)
2010-09-16 12:33 1456将 Acegi 集成到 ... -
Spring Security Acegi 学习之路一 (转)
2010-09-16 12:32 1391概述 Acegi Sec ... -
spring security详解教程 (转)
2010-09-16 12:29 2205先来谈一谈 Acegi 的基础知识, Acegi 的架 ... -
Spring的监听器 ContextLoaderListener的作用(转)
2010-07-07 11:18 1850在SSH项目中我们自动加载spring配置文件需要在web.x ...
相关推荐
Acegi是Spring早期的一个安全组件,后来发展成为Spring Security,是Spring生态系统中的重要部分,用于提供全面的安全解决方案。 Spring Security(原名Acegi Security)是一个强大的框架,用于保护基于Spring的...
spring_acegi精彩实例,带MYSQL数据库脚本,保证能运行 spring_acegi精彩实例,带MYSQL数据库脚本,保证能运行 spring_acegi精彩实例,带MYSQL数据库脚本,保证能运行 spring_acegi精彩实例,带MYSQL数据库脚本,...
在Spring框架中,Acegi(现在已经并入Spring Security)是一个强大的安全管理组件,它提供了认证和授权功能。在本文中,我们将深入探讨Spring_Acegi框架如何实现授权机制,特别是通过`FilterSecurityInterceptor`来...
Acegi Security(现已被Spring Security替代)是一个功能强大的安全框架,它主要解决了认证(Authentication)和授权(Authorization)这两个核心的安全问题。 首先,让我们理解认证和授权的基本概念: - **认证**...
Spring Security 的前身是 Acegi Security,它于 2004 年发布。2006 年,Acegi 被集成到 Spring 框架中,并改名为 Spring Security。自此之后,Spring Security 成为了 Spring 生态系统中的一个重要组成部分,不断...
<bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <sec:filter-security-metadata-source> **" access="ROLE_ADMIN"/> **" access="IS_...
而在安全方面,Spring曾提供了一个名为Acegi Security的模块,它是Spring早期的一个安全解决方案,用于实现复杂的认证和授权需求。本文将深入探讨Spring的Acegi应用及其核心概念。 **1. Acegi Security简介** Acegi...
Spring Security 最初是由 Luke Taylor 和 Ray Ryan 开发的名为 Acegi Security 的项目,在 2005 年被并入 Spring 项目,并重新命名为 Spring Security。自那时起,Spring Security 经历了多个版本的迭代,不断地...
Acegi Security提供了一套基于Spring的认证和授权机制,但在Spring Security 2.x版本之后,大部分功能已被Spring Security自身所取代。 3. **spring-security-core-tiger-2.0.5.RELEASE-tests.jar**:这是一个测试...
Spring Security是一个功能强大且可高度定制的身份验证和访问控制...Spring Security Reference作为官方文档,是学习和应用Spring Security的重要资源,建议深入研究以充分利用其提供的功能来增强应用程序的安全性。
在从Acegi安全框架转换到Spring Security 2.0时,一个重要的变化就是如何将授权信息存储从XML配置文件迁移到数据库。这使得授权策略更加灵活,易于管理和维护。 24.1. Spring Security简介 Spring Security 2.0...
而Acegi Security(现在已经更名为Spring Security)是Spring生态体系中的一个强大安全组件,用于处理应用程序的安全访问控制。Ehcache则是一个广泛使用的内存缓存系统,它可以帮助提高应用性能,通过缓存数据来减少...
3. **过滤器安全链(Filter Security Interceptor)**:Acegi的核心组件之一,它是Servlet过滤器,负责拦截请求并根据配置的策略进行身份验证和授权。 4. **安全性配置(Security Configurations)**:在Spring应用...
- **发展历程**:Spring Security的发展历程可以追溯到早期的ACEGI Security项目,后来被集成到Spring框架中,并经过多次迭代更新,形成了如今功能强大且灵活的Spring Security框架。 - **获取方式**: - **项目...
- **历史**: 本章节简要回顾了 Spring Security 的发展历程,包括其前身 Acegi 安全框架的历史背景。 - **版本编号**: 明确了 Spring Security 版本的命名规则,例如 `3.2.0.M2` 中的 `.M2` 表示这是一个里程碑版本...
在阅读《Spring ACEGI手册(部分)》.doc文档时,可以深入学习如何配置和使用该框架,以及如何解决常见的安全问题。 **总结** Spring ACEGI作为一个强大的安全框架,为开发者提供了丰富的工具和机制来保护应用程序...
总的来说,《Acegi(Spring Security)参考手册》是学习和理解Spring Security不可或缺的资源,无论你是初学者还是有经验的开发者,都能从中获取到实用的知识和深入的理解,以构建更加安全、健壮的Spring应用。...