Spring中给jdbc.properties属性文件进行密文处理

一般spring容器启动时,通过PropertyPlaceholderConfigurer类读取jdbc.properties文件里的数据库配置信息。

通过这个原理,我们把加密后的数据库配置信息放到jdbc.properties文件里,然后自定义一个继承PropertyPlaceholderConfigurer的类,实现解密,把解密后的信息又放回去。最后在配置DataSource时,还是用占位符${}取配置信息。本次采用的加密方式是通过MD5根据自定义键来进行加密

jdbc.properties文件:

#加密前
#jdbc.driver=数据库驱动
#jdbc.url=数据库连接地址
#jdbc.username=用户名
#jdbc.password=密码

#加密后
jdbc.driver.encryption=A551966A9AF762B92501746C2CB01B106C34B140337ADE6E602DF5FB0DA173DB
jdbc.url.encryption=4042C4E947DE0ABDE395A65B56BAC61828773933A8D94B913BED7648490C3A15683550FB33253ECD18A5C62C237FC824
jdbc.username.encryption=4DD8268D320D25322A3AAE2A37DABABA
jdbc.password.encryption=BAE996B948645DA06922BE240FF3FBBB

上面加密后的东西,要先通过工具类将加密前的数据进行加密,然后再放入jdbc.properties文件中,同时注释掉加密前的内容

工具类AESHelper:

package com.lyh.domain;

import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
/**
* @author 作者:LYH
* @createDate 创建时间:2018年8月14日 上午8:37:31
*/
public class AESHelper {
    Cipher ecipher;
    
    Cipher dcipher;
    
    /**
     * Input a string that will be md5 hashed to create the key.
     * 
     * @return void, cipher initialized
     */
    public AESHelper() {
        try {
            SecretKeySpec skey = new SecretKeySpec("0123456789ABCDEF".getBytes(), "AES");
            this.setupCrypto(skey);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public AESHelper(String key) {
        SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
        this.setupCrypto(skey);
    }
    
    private void setupCrypto(SecretKey key) {
        // Create an 8-byte initialization vector
        byte[] iv = new byte[]
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        
        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
        try {
            ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            
            // CBC requires an initialization vector
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // Buffer used to transport the bytes from one stream to another
    // byte[] buf = new byte[1024];
    
    public void encrypt(InputStream in, OutputStream out) {
        byte[] buf = new byte[1024];
        try {
            // Bytes written to out will be encrypted
            out = new CipherOutputStream(out, ecipher);
            
            // Read in the cleartext bytes and write to out to encrypt
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        }
        catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Input is a string to encrypt.
     * 
     * @return a Hex string of the byte array
     */
    public String encrypt(String plaintext) {
        try {
            byte[] ciphertext = ecipher.doFinal(plaintext.getBytes("UTF-8"));
            return byteToHex(ciphertext);
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        
    }
    
    public void decrypt(InputStream in, OutputStream out) {
        try {
            byte[] buf = new byte[1024];
            // Bytes read from in will be decrypted
            in = new CipherInputStream(in, dcipher);
            
            // Read in the decrypted bytes and write the cleartext to out
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        }
        catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Input encrypted String represented in HEX
     * 
     * @return a string decrypted in plain text
     */
    public String decrypt(String hexCipherText) {
        try {
            String plaintext = new String(dcipher.doFinal(hexToByte(hexCipherText)), "UTF-8");
            return plaintext;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public String decrypt(byte[] ciphertext) {
        try {
            String plaintext = new String(dcipher.doFinal(ciphertext), "UTF-8");
            return plaintext;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    private static byte[] getMD5(String input) {
        try {
            byte[] bytesOfMessage = input.getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("MD5");
            return md.digest(bytesOfMessage);
        }
        catch (Exception e) {
            return null;
        }
    }
    
    static final String HEXES = "0123456789ABCDEF";
    
    public static String byteToHex(byte[] raw) {
        if (raw == null) {
            return null;
        }
        final StringBuilder hex = new StringBuilder(2 * raw.length);
        for (final byte b : raw) {
            hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
        }
        return hex.toString();
    }
    
    public static byte[] hexToByte(String hexString) {
        int len = hexString.length();
        byte[] ba = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            ba[i / 2] =
                (byte)((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
        }
        return ba;
    }
    
//测试加密
	public static void main(String[] args){
		  AESHelper aesHelper = new AESHelper();
		  System.out.println(aesHelper.encrypt("com.mysql.jdbc.Driver"));
	}

}

进行解密的类实现了PropertyPlaceholderConfigurer

GvtvPropertyPlaceholderConfigurer.java

package com.lyh.domain;

import java.util.Enumeration;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

/**
* @author 作者:LYH
* @createDate 创建时间:2018年8月14日 上午8:35:29
*/
public class GvtvPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
        
        AESHelper aesHelper = new AESHelper();
        Enumeration<?> keys = props.propertyNames();
        while (keys.hasMoreElements()) {
            String key = (String)keys.nextElement();
            String value = props.getProperty(key);
            if (key.endsWith(".encryption") && null != value) {
                props.remove(key);
                key = key.substring(0, key.length() - 11);
                value = aesHelper.decrypt(value.trim());
                props.setProperty(key, value);
            }
            System.setProperty(key, value);
        }
        
        super.processProperties(beanFactoryToProcess, props);
    }
}

下面是spring的配置文件,用来读取xml中的内容:

<bean id="propertyConfigurer"
		class="com.lyh.domain.GvtvPropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath*:jdbc.properties</value>
			</list>
		</property>
	</bean>

	<!-- 使用dbcp配置 数据库链接池 -->
	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
		destroy-method="close" lazy-init="true" depends-on="propertyConfigurer">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	<!-- 取得sqlsessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />

com.lyh.domain.GvtvPropertyPlaceholderConfigurer这是自定义的类

到这里后加密解密就完成了,想要看到更加的直观的可以下载代码https://download.csdn.net/download/qq_36827957/10602489

猜你喜欢

转载自blog.csdn.net/qq_36827957/article/details/81663132