- 浏览: 156139 次
- 性别:
- 来自: 奥克兰
文章分类
最新评论
-
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 1664Spring MVC中修改校验的异常信息 原文转自: ... -
Spring 3之MVC & Security简单整合开发(三)
2011-03-01 11:01 1274为了方便学习,原文转自http://sarin.iteye.c ... -
Spring 3之MVC & Security简单整合开发(二)
2011-03-01 10:59 2090为了方便学习,原文出自http://sarin.iteye.c ... -
Spring 3之MVC & Security简单整合开发(一)(转)
2011-03-01 10:58 1539为了方便学习,原文出自http://sarin.iteye.c ... -
Spring与Hibernate两种组合方式 (转)
2010-10-07 17:31 1860Spring与Hibernate大致有两种组合方式,主要区别是 ... -
Spring Security Acegi 学习之路四 (转)
2010-09-16 12:34 1657安全对象访问控制 Aceg ... -
Spring Security Acegi 学习之路二(转)
2010-09-16 12:33 1433将 Acegi 集成到 ... -
Spring Security Acegi 学习之路一 (转)
2010-09-16 12:32 1374概述 Acegi Sec ... -
spring security详解教程 (转)
2010-09-16 12:29 2160先来谈一谈 Acegi 的基础知识, Acegi 的架 ... -
Spring的监听器 ContextLoaderListener的作用(转)
2010-07-07 11:18 1811在SSH项目中我们自动加载spring配置文件需要在web.x ...
相关推荐
spring_acegi精彩实例,带MYSQL数据库脚本,保证能运行 spring_acegi精彩实例,带MYSQL数据库脚本,保证能运行 spring_acegi精彩实例,带MYSQL数据库脚本,保证能运行 spring_acegi精彩实例,带MYSQL数据库脚本,...
spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+acegi+中文手册spring+...
Acegi Security System for Spring
Spring源代码解析(十):Spring_Acegi框架授权的实现.doc
Spring Acegi权限控制,安全系统就只包括两个问题: 认证和授权.
Acegi文档 spring acegi 详细文档
基于spring的Acegi安全框架认证与授权的分析及扩展.pdf
Spring Security acegi
NULL 博文链接:https://liaomin789.iteye.com/blog/581234
前段时间复习了spring怎么做权限的技术,spring acegi 学习心得.记下来勉励自己.
Spring的ACEGI的应用
16. acegi到spring security的转换方式 16.1. Spring Security是什么 16.2. 目标 16.3. 步骤 16.4. 总结 V. 高级话题 17. 领域对象安全(ACLs) 17.1. 概述 17.2. 关键概念 17.3. 开始 18. 预认证...
pring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。 Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发的企业软件...
这里包括Spring Security2的中文文档和一个基于Dao的开发实例,相信不管是对原来基于Acegi安全框架的开发人员还是现在基于Spring安全框架(Spring Security2实际上是Acegi2)的开发人员都有参考价值.
spring Acegi例子,很简单的一个acegi实例,容易理解
1、搭建基本的Spring Security项目 2、使用数据库管理用户权限 3、自定义认证数据库表结构 4、自定义登录页面 5、使用数据库管理资源 6、控制用户信息 MD5加密 获取当前用户信息 7、自定义访问拒绝页面 8、动态...
Spring acegi 3 文档 Spring acegi 3 文档Spring acegi 3 文档 Spring acegi 3 文档
Spring ACEGI手册(部份) 博文链接:https://allenj2ee.iteye.com/blog/129321
Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。
Spring源代码解析(九):Spring_Acegi框架鉴权的实现.doc