属性userMap使用一个org.acegisecurity.userdetails.memory.UserMap对象来定义一组用户名、密码和权限。幸运的是,当装配一个InMemoryDaoImpl时,你不必为配置一个UserMap实例而操心,因为Acegi提供了一个属性编辑器,它能够帮你把一个字符串转化为一个UserMap对象。
以上的 authenticationDao声明中定义了三个用户:palmerd、bauerj、myersn。这三个用户的密码分别是4moreyears,ineedsleep和traitor。用户palmerd被定义为拥有权限ROLE_PRESIDENT,bauerj被赋予权限ROLE_FIELD_OPS和ROLE_DIRECTOR,并且用户myersn被给予ROLE_CENTRAL_OPS授权。
JdbcDaoImpl是一个简单而灵活的认证DAO。以它最简单的形势,只需要一个javax.sql.DataSource对象的引用,可以通过以下方式在Spring配置文件中进行声明:
- <bean id="authenticationDao"
- class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
- <property name="dataSource">
- <ref bean="dataSource"/>
- property>
- bean>
JdbcDaoImpl假设你在数据库中已经建立了某些用于存放用户信息的表。特别地,它假设有一张“Users”表和一张“授权”表,如图:
当JdbcDaoImpl查找用户信息时,它会使用“SELECT username,password,enabled FROM users WHERE username = ?”作为查询语句。类似地,当查找授权时,它会使用“SELECT username,authority FROM authorities WHERE username = ?”。
尽管JdbcDaoImpl假定的表结构非常直接,它们很可能与你已经为应用系统建立的表结构不一致。比如,在Spring培训应用中,Student表保存用户名(在login列中)和密码。是否这意味着你无法在Spring培训应用中使用JdbcDaoImpl来验证学生的身份?
当然不是。但你必须通过设置usersByUserNameQuery属性告诉JdbcDaoImpl如何找到用户信息。下面是对authenticationDao Bean的调整使它更适合Spring培训应用:
- <bean id="authenticationDao"
- class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
- <property name="dataSource">
- <ref bean="dataSource"/>
- property>
- <property name="usersByUserNameQuery">
- <value>
- SELECT login,password FROM student WHERE login=?
- value>
- property>
- bean>
现在JdbcDaoImpl知道如何在Student表中查找用户的认证信息了。但是,还有一件事遗漏了。Student表中没有标志表明用户是否被禁用。事实上,我们一直假设所有的学生都是未被禁用的。但我们如何告诉JdbcDaoImpl做同样的假设?
JdbcDaoImpl还有一个usersByUserNameMapping属性,它引用一个MappingSqlQuery实例。MappingSqlQuery的mapRow()方法将一个ResultSet中的字段映射为一个领域对象。对于JdbcDaoImpl,提供给usersByUserNameMapping属性的MappingSqlQusery对象要求能够将一个ResultSet(通过执行用户查询获得)转化为一个
org.acegisecurity.userdetails.UserDetails对象。
UsersByUserNameMapping显示了一个MappingSqlQuery的实现,它适合将学生用户表的一个查询结果转换为一个UserDetails对象。它从ResultSet中抽取出username和password,但总是设置enabled属性为true。
- public class UsersByUsernameMapping extends MappingSqlQuery{
- protected UsersByUsernameMapping(DataSource dataSource){
- super(dataSource,usersByUsernameQuery);
- declareParameter(new SqlParameter(Types.VARCHAR));
- compile();
- }
- protected Object mapRow(ResultSet rs,int rownum) throws SQLException{
- String username=rs.getString(1);
- String password=rs.getString(2);
-
- UserDetails user=new User(username,password,true,
- new GrantedAuthority[]{new GrantedAuthorityImpl("HOLDER")});
- return user;
- }
- }
剩下唯一需要做的事就是声明一个UsersByUsernameMapping Bean,并将它装配到usersByUserNameMapping属性中。以下的authenticationDao Bean的声明将一个内部Bean装配至usersByUserNameMapping属性中,从而可以应用新的用户映射:
- <bean id="authenticationDao"
- class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
- <property name="dataSource">
- <ref bean="dataSource"/>
- </property>
- <property name="usersByUserNameQuery">
- <value>
- SELECT login,password FROM student WHERE login=?
- </value>
- </property>
- <property name="usersByUserNameMapping">
- <bean class="my.UsersByUsernameMapping"/>
- </property>
- </bean>
你也能改变 JdbcDaoImpl查询用户权限的方式。与属性usersByUserNameQuery和usersByUserNameMapping定义JdbcDaoImpl如何查询用户认证信息相同,属性authoritiesByUserNameQuery和authoritiesByUserNameMapping告诉JdbcDaoImpl如何查询用户的权限:例如,你可以使用以下代码从user_privileges表中查询已授予一个用户的权限。
- <bean id="authenticationDao"
- class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
- <property name="dataSource">
- <ref bean="dataSource"/>
- </property>
- <property name="usersByUserNameQuery">
- <value>
- SELECT login,password FROM student WHERE login=?
- </value>
- </property>
- <property name="usersByUserNameMapping">
- <bean class="my.UsersByUsernameMapping"/>
- </property>
- <property name="authoritiesByUserNameQuery">
- <value>
- SELECT login,privilege FROM user_privileges where login=?
- </value>
- </property>
- </bean>
你可以将属性authoritiesByUserNameMapping设置成一个定制的MappingSqlQuery对象,从而可以定制权限查询的结果如何映射为一个org.acegisecurity.GrantedAuthority对象。但是,由于默认的MappingSqlQuery对上面给出的查询来说已经足够了,我们就不再画蛇添足了。
使用加密的密码
默认地,DaoAuthenticationProvider假设用户的密码是以明文方式(未加密的方式)存储的。但在与数据库中取出的密码进行比较之前,可以使用一个密码编码器加密用户输入的明文密码。下面介绍Acegi提供的三个密码编码器:
1. 默认) 不对密码进行编码,直接返回未经改变的密码;PlaintextPasswordEncoder(
2. 对密码进行消息摘要(MD5)加密;Md5PasswordEncoder
3. 对密码进行安全哈希算法(SHA)编码。ShaPasswordEncoder
你可以通过设置DaoAuthenticationProvider的passwordEncoder属性改变它的密码编码器。例如,要使用MD5编码可以用以下代码:
<property name="passwordEncoder""></property>
<bean class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"></bean>
你也需要设置编码器的种子源(salt source)。一个种子源为编码提供种子(salt),或者称编码的密钥。下面是Acegi提供的两个种子源:
1. 使用用户的User对象中某个指定的属性来获取种子;ReflectionSaltSource
2. 对系统中所有用户使用相同的种子。SystemWideSaltSource
SystemWideSaltSource适用于大多数情形。以下一段XML将一个SystemWideSaltSource装配到DaoAuthenticationProvider的saltSource属性中:
- <property name=saltSource">
- <bean class="org.acegisecurity.providers.dao.salt.SystemWideSaltSource">
- <property name="systemWideSalt">
- <value>123abcvalue>
- property>
- bean>
- property>
(这个种子其实就是在原由的字符串后追加上这个指定的字符串,然后再叫给Md5加密)
ReflectionSaltSource使用用户对象的某个特定属性作为用户密码的编码种子。由于这意味着每个用户的密码都会以不同的方式编码,因此更安全。若要装配一个ReflectionSaltSource,可以通过如下方式将它装配到saltSource属性中:
- <property name=saltSource">
- <bean class="org.acegisecurity.providers.dao.salt.ReflectionSaltSource">
- <property name="userPropertyToUse">
- <value>userNamevalue>
- property>
- bean>
- property>
-
在这里,用户的userName属性被用作种子来加密用户的密码。要特别重视的是必须保证种子是静态的,永远不会改变;否则,一旦种子改变,就再也不可能对用户身份进行验证了,因为MD5是不可逆的。
缓存用户信息
每次当请求一个受保护的资源时,认证管理起就被调用以获取用户的安全信息。但如果获取用户信息涉及到查询数据库,每次都查询相同的数据可能在性能上表现得很糟糕。注意到用户信息不会频繁改变,也许更好的做法是在第一次查询时缓存用户信息,并在后续的查询中直接从缓存中获取用户信息。
DaoAuthenticationProvider通过org.acegisecurity.providers.dao.UserCache接口的实现类支持对用户信息进行缓存。
- public interface UserCache {
- UserDetails getUserFromCache(String username);
- void putUserInCache(UserDetails user);
- void removeUserFromCache(String username);
- }
顾名思义,接口UserCache中方法提供了向缓存中放入、取得和删除用户明细信息的功能。写一个你自己的UserCache实现类是相当简单的。然而,在你考虑开发自己的UserCache实现类之前,应该首先考虑Acegi提供的两个方便的UserCache实现类:
1. org.acegisecurity.providers.dao.cache. NullUserCache
2. org.acegisecurity.providers.dao.cache. EhCacheBasedUserCache
NullUserCache事实上不进行任何缓存。任何时候调用它的getUserFromCache方法,得到的返回值都是null。这是DaoAuthenticationProvider使用的默认UserCache实现。
EhCacheBasedUserCache是一个更实用的缓存实现。类如其名,它是基于开源项目ehcache实现的。Ehcache是一个简单快速的针对Java的缓存解决方案,同时也是Hibernate默认的和推荐的缓存方案。
在DaoAuthenticationProvider中使用ehcache是很简单的,只需要简单地声明一个EhCacheBasedUserCase Bean即可:
- <bean id=userCache"
- class="org.acegisecurity.providers.dao.cache. EhCacheBasedUserCache">
- <property name="minutesToIdle">15property>
- bean>
属性minutesToIdle告诉缓存器一条用户信息在没有访问的情况下应该在缓存中保存多久。这里,我们设定在15分钟的非活动期后删除该条用户信息。
声明了userCache Bean之后,下面唯一要做的事就是把它装配到DaoAuthenticationProvider的userCache属性中:
- <bean id="authenticationProvider"
- class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
- <property name="userCache">
- <ref bean="userCache"/>
- property>
- bean>
2.3根据LDAP仓库进行身份验证(未完,代续)
2.4基于Acegi和Yale CAS实现单次登录(未完,代续)
相关推荐
一个使用Acegi身份认证框架的笔记 可以节省你的时间 方便快速学会使用
Acegi安全系统介绍 1 1.1 介绍 1 1.2 管理身份验证 3 1.3 控制访问 20 1.4 保护Web应用程序 24 1.5 保护方法调用 29 1.6 领域对象安全(Domain Object Security) 31
acegisecurity 数据验证 身份验证 如何实现java程序的验证
在身份验证层面,Spring Security广泛支持各种身份验证模式,这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering Task Force.作为补充,Spring Security 也提供了...
11.2 管理身份验证 11.2.1 配置ProviderManager 11.2.2 根据数据库验证身份 11.2.3 根据LDAP仓库进行身份验证 11.2.4 基于Acegi和Yale CAS实现单次登录 11.3 控制访问 11.3.1 访问决策...
在身份验证层面,Spring Security广泛支持各种身份验证模式,这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering Task Force.作为补充,Spring Security 也提供了...
请注意:没有时间自己完成 jSai; 我遇到了 ACEGI 项目,我现在推荐它。 杰赛; Servlet 身份验证实现。 jSai 旨在为 Java Servlet 提供更易于使用、更强大的身份验证。
11.3 身份验证 11.4 关于安全的插件 11.4.1 Acegi 11.4.2 JSecurity 12 插件 12.1 创建和安装插件 12.2 理解插件的结构 12.3 提供基础的工件 12.4 评估规约 12.5 参与构建事件 12.6 参与运行时配置 12.7 运行时添加...
产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,...
产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,...
24. 替换验证身份 24.1. 概述 24.2. 配置 A. 安全数据库表结构 A.1. User 表 A.1.1. 组权限 A.2. 持久登陆(Remember-Me)表 A.3. ACL 表 A.3.1. Hypersonic SQL A.3.1.1. PostgreSQL B. 安全...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...
Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮...