学习Acegi应用到实际项目中(5)
实际企业应用中,用户密码一般都会进行加密处理,这样才能使企业应用更加安全。既然密码的加密如此之重要,那么Acegi(Spring Security)作为成熟的安全框架,当然也我们提供了相应的处理方式。
针对用户密码的加密工作,DaoAuthenticationProvider同时暴露了passwordEncoder和saltSource属性。PasswordEncoder和SaltSource是可选的属性,PasswordEncoder负责对认证库中的密码进行加解密。而SaltSource则是在产生密码时给它加点“盐”,以增强密码在认证库中的安全性。Acegi安全系统提供的PasswordEncoder实现中包括MD5、SHA和明文编码。
Acegi提供了三种加密器:
PlaintextPasswordEncoder---默认,不加密,返回明文.
ShaPasswordEncoder---哈希算法(SHA)加密
Md5PasswordEncoder---消息摘要(MD5)加密
Acegi安全系统提供了两个SaltSource的实现:
SystemWideSaltSource,它用同样的"盐"对系统中所有的密码进行编码
ReflectionSaltSource只对从UserDetails对象返回的获得这种"盐"的指定属性进行检查。请参考JavaDoc以获取对这些可选特性的更详细信息。
图1为Acegi内置的PasswordEncoder继承链。默认时,DaoAuthenticationProvider会实例化PlaintextPasswordEncoder对象,即应对用户密码未进行加密处理的情况。
图2为Acegi内置的SaltSource继承链。默认时,SaltSource的取值为null,即未启用密码私钥。
1、 PlaintextPasswordEncoder明文密码
在使用明文密码期间,如果系统允许登录用户不区分密码大小写,则应设置ignorePasswordCase属性值为true。
在Acegi安全配置文件中添加:
<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)加密
在Acegi安全配置文件中添加:
<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)加密
在Acegi安全配置文件中添加:
<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
SystemWideSaltSource会采用一个静态字符串表示密码私钥(salt),所有用户的密码处理都会采用这一私钥。与未启用密码私钥相比,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
尽管采用SystemWideSaltSource能够加强密码的保护,但由于SystemWideSaltSource采用了全局性质的密码私钥,因此仍存在一定的缺陷。
而ReflectionSaltSource采用了个案性质的密码私钥,即其密码加密所采用的私钥是动态变化的,因此它更为安全。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}”的形式进行加密处理。
通过指定userPropertyToUse属性的值,开发者能够控制密码私钥的来源。比如上述的getUsername的含义就是动态调用相应的getUsername()方法,并将返回结果直接作为密码的私钥。在实际企业应用中,Acegi应用开发者可能会提供自身的UserDetails实现类,这时userPropertyToUse属性的取值范围更加广泛。
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();
} }
学习Acegi应用到实际项目中(5)的更多相关文章
- 学习Acegi应用到实际项目中(10)- 保护业务方法
前面已经讲过关于保护Web资源的方式,其中包括直接在XML文件中配置和自定义实现FilterInvocationDefinitionSource接口两种方式.在实际企业应用中,保护Web资源非常重要, ...
- 学习Acegi应用到实际项目中(2)
Acegi应用到实际项目中(1)是基于BasicProcessingFilter的基本认证,这篇改用AuthenticationProcessingFilter基于表单的认证方式. 1.authent ...
- 学习Acegi应用到实际项目中(7)- 缓存用户信息
在默认情况下,即在用户未提供自身配置文件ehcache.xml或ehcache-failsafe.xml时,EhCache会依据其自身Jar存档包含的ehcache-failsafe.xml文件所定制 ...
- 学习Acegi应用到实际项目中(1)
在此,本人声明,我处于菜鸟阶段,文章的内容大部分摘自zhanjia的博客(http://zhanjia.iteye.com/category/43399),旨在学习,有很多地方,我理解不够透彻,可能存 ...
- 学习Acegi应用到实际项目中(12)- Run-As认证服务
有这样一些场合,系统用户必须以其他角色身份去操作某些资源.例如,用户A要访问资源B,而用户A拥有的角色为AUTH_USER,资源B访问的角色必须为AUTH_RUN_AS_DATE,那么此时就必须使用户 ...
- 学习Acegi应用到实际项目中(11)- 切换用户
在某些应用场合中,可能需要用到切换用户的功能,从而以另一用户的身份进行相关操作.这一点类似于在Linux系统中,用su命令切换到另一用户进行相关操作. 既然实际应用中有这种场合,那么我们就有必要对其进 ...
- 学习Acegi应用到实际项目中(9)- 实现FilterInvocationDefinition
在实际应用中,开发者有时需要将Web资源授权信息(角色与授权资源之间的定义)存放在RDBMS中,以便更好的管理.事实上,一般的企业应用都应当如此,因为这样可以使角色和Web资源的管理更灵活,更自由.那 ...
- 学习Acegi应用到实际项目中(8)- 扩展UserDetailsService接口
一个能为DaoAuthenticationProvider提供存取认证库的的类,它必须要实现UserDetailsService接口: public UserDetails loadUserByUse ...
- 学习Acegi应用到实际项目中(4)
此节介绍:ConcurrentSessionFilter. 在Acegi 1.x版本中,控制并发HttpSession和Remember-Me认证服务不能够同时启用,它们之间存在冲突问题. 在一些应用 ...
随机推荐
- MySQL SQL审核平台 inception+archer2.0(亲测)
docker run -d --privileged -v `pwd`/archer_data:/data -p 9306:3306 --name archer --hostname archer - ...
- 根据url路径获取图片并显示到ListView中
项目开发中我们需要从网络获取图片显示到控件中,很多开源框架如Picasso可以实现图片下载和缓存功能.这里介绍的是一种简易的网络图片获取方式并把它显示到ListView中. 本案例实现的效果如下: 项 ...
- 将打印(printk/printf)及时写入文件的方法
问题是这样的,在测试一个gps的app的时候,我使用脚本 “ gps_test_app > /tmp/gps_log.txt &" 但是但是,去查看gps_log.txt的 ...
- 涂抹mysql笔记-搭建mysql高可用体系
mysql的高可用体系<>追求更高稳定性的服务体系 可扩展性:横向扩展(增加节点).纵向扩展(增加节点的硬件配置) 高可用性<>Slave+LVS+Keepalived实现高可 ...
- maven仓库配置阿里云镜像
maven仓库的默认镜像为国外镜像,下载jar包依赖非常慢,可以将镜像设置为国内的阿里云. 只需要在maven的conf的setting中配置如下: <mirrors> <mirro ...
- 学习MeteoInfo二次开发教程(七)
1.站点文件 12010615.syn在D:\Program Files (x86)\MeteoInfo\SampleSYNOP_Stations.csv在D:\Program Files (x86) ...
- 关于AsyncSocket
写篇博客,在我项目中用到了一个很重要的第三方---AsyncSocket,写下我对AsyncSocket使用心得.我的项目中是APP对硬件直接交互,APP对硬件发指令的时候不需要 ...
- jquery:获取checked复选框的问题
jquery:获取checked复选框的问题 功能描述:要完成一个全选的功能,但总是获取不到复选框的被选中的个数,究其原因,是Jquery中length和checked使用不当所造成的. // 获取所 ...
- WPF 后台重写 DataTemplate
/// <summary> /// 配置类 /// </summary> public static class GridControlDeploy { /// <sum ...
- scrapy-pipeline的方法
scrapy中多个pipeline作用: 一个项目可能需要爬取多个网站,根据每个网站的数据量(处理方式)不同,可创建多个管道 pipeline class SpideranythingPipeline ...