Spring 配置数据库用户名密码加密

Posted 汤高

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 配置数据库用户名密码加密相关的知识,希望对你有一定的参考价值。

 

Spring 配置数据库用户名密码加密

传统形式配置数据库用户名密码

对于一般的spring框架,经常要用到数据源配置,如果是用xml配置的话,一般都是如下形式

 

数据库用户名密码密文配置实现

现在的需求是不能在配置文件里明文配置数据库用户名和密码

新增密文属性文件

class目录新增jdbc.properties配置文件,里面配置数据库用户名和密码的密文

修改spring数据库配置为占位符

修改spring数据库配置,如下

引入密文配置文件jdbc.properties

并在spring文件开头中加入如下配置,引入jdbc.properties文件

<bean id="propertyConfigurer"
		  class="com.ai.common.util.EncrypPropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
			</list>
		</property>
</bean>

自定义spring属性占位符处理类

EncrypPropertyPlaceholderConfigurer为自定义的,实现spring读取配置文件中的占位符,并且解析,注入解密后的数据库用户名和密码

public class EncrypPropertyPlaceholderConfigurer extends
        PropertyPlaceholderConfigurer 
    private Logger log= Logger.getLogger(EncrypPropertyPlaceholderConfigurer.class);

    @Override
    protected void processProperties(
            ConfigurableListableBeanFactory beanFactoryToProcess,
            Properties props) throws BeansException 
        String username = props.getProperty("jdbc.username");
        if (username != null) // 将加密的username解密后塞到props
            String user = SymmetricEncoder.AESDncode(username);
            props.setProperty("jdbc.username", SymmetricEncoder.AESDncode(username));
        
        String password = props.getProperty("jdbc.password");
        if (username != null) 
            props.setProperty("jdbc.password",
                    SymmetricEncoder.AESDncode(password));
        
        super.processProperties(beanFactoryToProcess, props);
    

    public static void main(String[] args) 
        String user="7Z3ekkmGFkOFjfpkNvg4cA==";
        System.out.println(AESCoderUtils.AESDncode(user));

    


 

自定义AES加密解密算法

加密解密工具类

/**
 * <p>description:</p>
 *
 * @author tanggao
 * @version 1.0
 * @date 2018/10/18
 */
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/*
 * AES对称加密和解密
 */
public class SymmetricEncoder 
    /*
     * 加密
     * 1.构造密钥生成器
     * 2.根据ecnodeRules规则初始化密钥生成器
     * 3.产生密钥
     * 4.创建和初始化密码器
     * 5.内容加密
     * 6.返回字符串
     */
    public static String AESEncode(String content)
        try 
            // 初始化算法,设置成“SHA1PRNG”是为了防止在linux环境下随机生成算法
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed("xxx".getBytes("utf-8"));
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen=KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            keygen.init(128, secureRandom);
            //3.产生原始对称密钥
            SecretKey original_key=keygen.generateKey();

            //4.获得原始对称密钥的字节数组
            byte [] raw=original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key=new SecretKeySpec(raw, "AES");

            //6.根据指定算法AES自成密码器
            Cipher cipher=Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte [] byte_encode=content.getBytes("utf-8");
            //9.根据密码器的初始化方式--加密:将数据加密
            byte [] byte_AES=cipher.doFinal(byte_encode);
            //10.将加密后的数据转换为字符串
            //这里用Base64Encoder中会找不到包
            //解决办法:
            //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
            String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
            //11.将字符串返回
            return AES_encode;
         catch (NoSuchAlgorithmException e) 
            e.printStackTrace();
         catch (NoSuchPaddingException e) 
            e.printStackTrace();
         catch (InvalidKeyException e) 
            e.printStackTrace();
         catch (IllegalBlockSizeException e) 
            e.printStackTrace();
         catch (BadPaddingException e) 
            e.printStackTrace();
         catch (UnsupportedEncodingException e) 
            e.printStackTrace();
        

        //如果有错就返加nulll
        return null;
    
    /*
     * 解密
     * 解密过程:
     * 1.同加密1-4步
     * 2.将加密后的字符串反纺成byte[]数组
     * 3.将加密内容解密
     */
    public static String AESDncode(String content)
        try 
            // 初始化算法,设置成“SHA1PRNG”是为了防止在linux环境下随机生成算法
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed("xxx".getBytes("utf-8"));

            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen=KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            keygen.init(128,secureRandom);
            //3.产生原始对称密钥
            SecretKey original_key=keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte [] raw=original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key=new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher=Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            //8.将加密并编码后的内容解码成字节数组
            byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
            byte [] byte_decode=cipher.doFinal(byte_content);
            String AES_decode=new String(byte_decode,"utf-8");
            return AES_decode;
         catch (NoSuchAlgorithmException e) 
            e.printStackTrace();
         catch (NoSuchPaddingException e) 
            e.printStackTrace();
         catch (InvalidKeyException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         catch (IllegalBlockSizeException e) 
            e.printStackTrace();
         catch (BadPaddingException e) 
            e.printStackTrace();
        

        //如果有错就返加nulll
        return null;
    

    public static void main(String[] args) throws Exception 

        if(args.length!=1)
            throw  new Exception("请输入需要加密的内容!");
        
        String user=args[0];

        String encrpt = AESEncode(user);
        System.out.println("加密后的密文为:"+encrpt);

        System.out.println(AESDncode(encrpt));
    

使用

ApplicationContext  context = new ClassPathXmlApplicationContext(xmlpath);

注意:必须使用 ClassPathXmlApplicationContext,不能使用

XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource(xmlpath));

XmlBeanFactory 这种方式不支持

ClassPathXmlApplicationContext为启动加载即实bean,XmlBeanFactory 为延迟实例化bean,如果原先是用的XmlBeanFactory ,而现在改为ClassPathXmlApplicationContext后因为启动加载bean报错,就在beans中加入 

或者在每个bean中加入

在beans中加入的default-lazy-init="true" 为全局设置,在bean中加入的lazy-init="true"为单个设置 ,单个设置优先局部

以上是关于Spring 配置数据库用户名密码加密的主要内容,如果未能解决你的问题,请参考以下文章

spring 加密 Druid 连接池—— 加密 url,driverClassName,用户名,密码

Spring Security PasswordEncoder

Spring Security学习——密码加密

Spring Security学习——密码加密

spring security 控制用户信息用户加密 缓存用户信息

Spring Security-用户密码自定义加密