spring boot+druid 多數據源的密碼加密

druid數據庫密碼加密很簡單,它提供了一個解密回調,我們只需要具體實現就可以了,加解密邏輯可以自己實現。

大體思路:

1、預先根據公鑰(自定義)生成加密密碼,配置在yml文件中

2、實現加解密算法。

3、編寫自己的回調類,實現自己的回調邏輯,並配置到yml中

一、配置文件(公鑰、密碼接口回調類)


yml文件:

spring:
  datasource:
    # 公鑰
    publicKey: GOURD-HXNLYW-201314
    type: com.alibaba.druid.pool.DruidDataSource
    master:
      url: jdbc:mysql://47.103.5.190:3306/gourd?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: hWm9HtDn605aupyXTuuA5Q==
      # 配置 connection-properties,啓用加密,配置公鑰。
      connection-properties: config.decrypt=true;publicKey=${spring.datasource.publicKey};password=${spring.datasource.master.password}
      passwordCallbackClassName: com.gourd.index.config.DbPasswordCallback
    slave:
      url: jdbc:mysql://47.103.5.190:3306/gourd?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: hWm9HtDn605aupyXTuuA5Q==
      # 配置 connection-properties,啓用加密,配置公鑰。
      connection-properties: config.decrypt=true;publicKey=${spring.datasource.publicKey};password=${spring.datasource.slave.password}
      passwordCallbackClassName: com.gourd.index.config.DbPasswordCallback

    druid:
      initial-size: 5
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 50
      max-pool-prepared-statement-per-connection-size: 20

二、加解密工具類(自定義):

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

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

/**
 * AesHope工具類
 *
 * @author: gourd
 *
 **/
@Slf4j
public class AesHopeUtil {
    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";

    /***
     * AES加密
     * @param password
     * @param content
     * @return
     * @throws Exception
     */
    public static String encrypt(String password, String content){
        //創建密碼器
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            byte[] bytes = content.getBytes("utf-8");
            //初始化密碼器
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(password));
            //加密
            byte[] bytes1 = cipher.doFinal(bytes);
            //通過BASE64轉碼返回
            return Base64.encodeBase64String(bytes1);
        } catch (NoSuchAlgorithmException e) {
            log.error("{}",e);
        } catch (NoSuchPaddingException e) {
            log.error("{}",e);
        } catch (BadPaddingException e) {
            log.error("{}",e);
        } catch (UnsupportedEncodingException e) {
            log.error("{}",e);
        } catch (IllegalBlockSizeException e) {
            log.error("{}",e);
        } catch (InvalidKeyException e) {
            log.error("{}",e);
        }
        return null;
    }

    /***
     * AES解密
     * @param password
     * @param content
     * @return
     * @throws Exception
     */
    public static String decryt(String password, String content) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            //使用密鑰初始化解密
            cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(password));
            byte[] bytes = cipher.doFinal(Base64.decodeBase64(content));
            return new String(bytes, "utf-8");
        } catch (NoSuchAlgorithmException e) {
            log.error("{}",e);
        } catch (NoSuchPaddingException e) {
            log.error("{}",e);
        } catch (BadPaddingException e) {
            log.error("{}",e);
        } catch (UnsupportedEncodingException e) {
            log.error("{}",e);
        } catch (IllegalBlockSizeException e) {
            log.error("{}",e);
        } catch (InvalidKeyException e) {
            log.error("{}",e);
        }
        return null;
    }

    /***
     * 生成加密密鑰
     * @param password
     * @return
     * @throws NoSuchAlgorithmException
     */
    private static SecretKeySpec getSecretKeySpec(final String password)  {
        //返回密鑰生成器對象
        KeyGenerator keyGenerator = null;
        try {
            keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password.getBytes());
            //設置AES密鑰長度
            keyGenerator.init(128, secureRandom);
            //生成一個密鑰
            SecretKey secretKey = keyGenerator.generateKey();
            //轉換爲AES密鑰
            return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            log.error("{}",e);
        }
        return null;
    }
}

三、回調類,實現自己的回調邏輯

import com.alibaba.druid.util.DruidPasswordCallback;
import com.gourd.common.utils.AesHopeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Properties;

/**
 * 數據庫回調密碼解密
 * 
 * @author gourd
 *
 */
@Component
@Slf4j
public class DbPasswordCallback extends DruidPasswordCallback {

	@Override
	public void setProperties(Properties properties) {
		super.setProperties(properties);
		String password = properties.getProperty("password");
		String publicKey = properties.getProperty("publicKey");
		if (StringUtils.isNotEmpty(password)) {
			try {
				//所以這裏的代碼是將密碼進行解密
				String sourcePassword = AesHopeUtil.decryt(publicKey, password);
				setPassword(sourcePassword.toCharArray());
			} catch (Exception e) {
				setPassword(password.toCharArray());
			}
		}
	}

	/**
	 * 生成加密後的密碼,放到yml中
	 * @param args
	 */
	public static void main(String[] args) {
		// 生成加密後的密碼,放到yml中
		String password = "gourd123";
		String pwd = AesHopeUtil.encrypt("GOURD-HXNLYW-201314",password);
		System.out.println(pwd);

		String source = AesHopeUtil.decryt("GOURD-HXNLYW-201314",pwd);
		System.out.println(source);
	}
}

到此就結束了。

Druid多數據源配置請移步:https://blog.csdn.net/HXNLYW/article/details/90519757

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章