zoukankan      html  css  js  c++  java
  • 学习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();  
        }  
      
    }  
  • 相关阅读:
    前端笔试题目总结——应用JavaScript函数递归打印数组到HTML页面上
    HTM5新增结构化元素&非结构化元素&新增属性详解
    HTML 5 与HTML 4 的区别
    HTML5框架、背景和实体、XHTML的使用规范
    百度前端笔试题目--css 实现一个带尖角的正方形
    HTML5表单提交和PHP环境搭建
    HTML5列表、块、布局
    HTML5 格式化、样式、链接、表格
    2020-09-13助教一周总结(第二周)
    2020-09-10上课小结
  • 原文地址:https://www.cnblogs.com/cainiaomahua/p/8890725.html
Copyright © 2011-2022 走看看