精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-10-25
在实际企业应用中,用户密码一般都会进行加密处理,这样才能使企业应用更加安全。既然密码的加密如此之重要,那么Acegi(Spring Security)作为成熟的安全框架,当然也我们提供了相应的处理方式。
针对用户密码的加密工作,DaoAuthenticationProvider同时暴露了passwordEncoder和saltSource属性。PasswordEncoder和SaltSource是可选的属性,PasswordEncoder负责对认证库中的密码进行加解密。而SaltSource则是在产生密码时给它加点“盐”,以增强密码在认证库中的安全性。Acegi安全系统提供的PasswordEncoder实现中包括MD5、SHA和明文编码。 Acegi安全系统提供了两个SaltSource的实现: 图1为Acegi内置的PasswordEncoder继承链。默认时,DaoAuthenticationProvider会实例化PlaintextPasswordEncoder对象,即应对用户密码未进行加密处理的情况。
图2为Acegi内置的SaltSource继承链。默认时,SaltSource的取值为null,即未启用密码私钥。
1、 PlaintextPasswordEncoder明文密码 <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="inMemDaoImpl" /> <!-- 增加 --> <property name="passwordEncoder" ref="plaintextPasswordEncoder" /> </bean> <!-- 增加 --> <bean id="plaintextPasswordEncoder" class="org.acegisecurity.providers.encoding.PlaintextPasswordEncoder"> <property name="ignorePasswordCase" value="true"></property> </bean>
2、 ShaPasswordEncoder哈希算法(SHA)加密 <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="inMemDaoImpl" /> <!-- 增加 --> <property name="passwordEncoder" ref="shaPasswordEncoder" /> <!-- <property name="passwordEncoder" ref="shaMessageDigestPasswordEncoder" /> --> </bean> <!-- 增加, 以下两种配置方式等效 --> <bean id="shaPasswordEncoder" class="org.acegisecurity.providers.encoding.ShaPasswordEncoder"> <constructor-arg> <value>256</value> </constructor-arg> <property name="encodeHashAsBase64" value="false"></property> </bean> <!-- <bean id="shaMessageDigestPasswordEncoder" class="org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder"> <constructor-arg> <value>SHA-256</value> </constructor-arg> <property name="encodeHashAsBase64" value="false"></property> </bean> -->
3、 Md5PasswordEncoder消息摘要(MD5)加密 <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="inMemDaoImpl" /> <!-- 增加 --> <property name="passwordEncoder" ref="md5PasswordEncoder" /> <!-- <property name="passwordEncoder" ref="md5MessageDigestPasswordEncoder" /> --> </bean> <!-- 增加. 以下两种配法等效 --> <bean id="md5PasswordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"> <property name="encodeHashAsBase64" value="false"></property> </bean> <!-- <bean id="md5MessageDigestPasswordEncoder" class="org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder"> <constructor-arg> <value>MD5</value> </constructor-arg> <property name="encodeHashAsBase64" value="false"></property> </bean> -->
4、 SystemWideSaltSource <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="userDetailsService" /> <property name="passwordEncoder" ref="md5PasswordEncoder" /><!-- 增加 --> <!-- 增加 --> <property name="saltSource"> <bean class="org.acegisecurity.providers.dao.salt.SystemWideSaltSource"> <property name="systemWideSalt" value="javaee"></property> </bean> </property> </bean>
5、 ReflectionSaltSource <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="userDetailsService" /> <property name="passwordEncoder" ref="md5PasswordEncoder" /> <!-- 增加 --> <property name="saltSource"> <bean class="org.acegisecurity.providers.dao.salt.ReflectionSaltSource"> <property name="userPropertyToUse" value="getUsername"></property> </bean> </property> </bean>
此时,ReflectionSaltSource将调用UserDetails对象的getUsername()方法获得各用户的密码私钥。比如:javaee(用户名)/password(密码) 用户的密码将被以“password{javaee}”的形式进行加密处理。
6、 在web.xml中,我提供了三种方式方便大家调试
<!-- <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext-acegi-security-plaintext.xml </param-value> </context-param> --> <!-- <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext-acegi-security-sha.xml </param-value> </context-param> --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext-acegi-security-md5.xml </param-value> </context-param> <!-- <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext-acegi-security-md5-salt.xml </param-value> </context-param>-->
7、 这里我提供了一个用于生成加密密码的类
package org.acegi.sample; import org.acegisecurity.providers.encoding.Md5PasswordEncoder; import org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder; import org.acegisecurity.providers.encoding.ShaPasswordEncoder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * 加密管理类 * * @author zhanjia * */ public class PasswordProcessing { private static final Log log = LogFactory.getLog(PasswordProcessing.class); public static void processMd5() { log.info("以MD5方式加密......................"); // 直接指定待采用的加密算法(MD5) MessageDigestPasswordEncoder mdpeMd5 = new MessageDigestPasswordEncoder("MD5"); // 生成32位的Hex版, 这也是encodeHashAsBase64的默认值 mdpeMd5.setEncodeHashAsBase64(false); log.info(mdpeMd5.encodePassword("password", null)); // 生成24位的Base64版 mdpeMd5.setEncodeHashAsBase64(true); log.info(mdpeMd5.encodePassword("password", null)); // 等效于上述代码 Md5PasswordEncoder mpe = new Md5PasswordEncoder(); mpe.setEncodeHashAsBase64(false); log.info(mpe.encodePassword("password", null)); mpe.setEncodeHashAsBase64(true); log.info(mpe.encodePassword("password", null)); } public static void processSha() { log.info("以SHA方式加密......................"); // 直接指定待采用的加密算法(SHA)及加密强度(256) MessageDigestPasswordEncoder mdpeSha = new MessageDigestPasswordEncoder("SHA-256"); mdpeSha.setEncodeHashAsBase64(false); log.info(mdpeSha.encodePassword("password", null)); mdpeSha.setEncodeHashAsBase64(true); log.info(mdpeSha.encodePassword("password", null)); // 等效于上述代码 ShaPasswordEncoder spe = new ShaPasswordEncoder(256); spe.setEncodeHashAsBase64(false); log.info(spe.encodePassword("password", null)); spe.setEncodeHashAsBase64(true); log.info(spe.encodePassword("password", null)); } public static void processSalt() { log.info("以MD5方式加密、加私钥(盐)......................"); Md5PasswordEncoder mpe = new Md5PasswordEncoder(); mpe.setEncodeHashAsBase64(false); // 等效的两行地代码 log.info(mpe.encodePassword("password{javaee}", null)); // javaee为密码私钥 log.info(mpe.encodePassword("password", "javaee")); // javaee为密码私钥 // 结果:87ce7b25b469025af0d5c6752038fb56 } /** * @param args */ public static void main(String[] args) { processMd5(); processSha(); processSalt(); } }
开发环境: Jar包:
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-10-31
<property name="userDetailsService" ref="inMemDaoImpl" />
<property name="userDetailsService" ref="userDetailsService" /> 这里的inMemDaoImpl, userDetailsService实现有没有什么要求? 是否必须是spring 的 DaoSupport 的实现? 自己的dao规范可否? |
|
返回顶楼 | |
发表时间:2008-11-01
raymond2006k 写道 <property name="userDetailsService" ref="inMemDaoImpl" />
<property name="userDetailsService" ref="userDetailsService" /> 这里的inMemDaoImpl, userDetailsService实现有没有什么要求? 是否必须是spring 的 DaoSupport 的实现? 自己的dao规范可否? 可以自己提供,也有一定的规范,请参考: 菜鸟-手把手教你把Acegi应用到实际项目中(8)-扩展UserDetailsService接口 http://zhanjia.iteye.com/blog/259441 |
|
返回顶楼 | |
发表时间:2009-07-28
使用MessageDigestPasswordEncoder,Md5PasswordEncoder,这些函数加密的,就没有解密的函数吗?我找了一下没找着,麻烦LZ告知!
|
|
返回顶楼 | |
发表时间:2009-07-29
用户密码一般都会进行加密处理,这样才能使企业应用更加安全。
windywindy 写道 使用MessageDigestPasswordEncoder,Md5PasswordEncoder,这些函数加密的,就没有解密的函数吗?我找了一下没找着,麻烦LZ告知!
数据验证,同样加密验证好啦,不用解密吧.. |
|
返回顶楼 | |
发表时间:2009-07-29
这标题起的:菜鸟,过来,我手把手教你配Acegi
|
|
返回顶楼 | |
发表时间:2009-07-30
这标题起的:菜鸟,过来,我手把手教你配Acegi ,比较牛
|
|
返回顶楼 | |
发表时间:2009-08-03
daquan198163 写道 这标题起的:菜鸟,过来,我手把手教你配Acegi
理解有误啊,是因为我觉得自己还是菜鸟。 意思是说:我是 菜鸟,我手把手教你... 请原谅啊,不要误导了人家,罪过... |
|
返回顶楼 | |
发表时间:2009-08-03
windywindy 写道 使用MessageDigestPasswordEncoder,Md5PasswordEncoder,这些函数加密的,就没有解密的函数吗?我找了一下没找着,麻烦LZ告知!
有些加密算法是可逆的,有些是不可逆的。 不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。所以比较安全 |
|
返回顶楼 | |
浏览 5754 次