文章目录

实现原理:
在获取SqlSessionFactory之前,对获取的配置信息做解密操作

1. 创建db.properties

properties配置文件
一般是使用properties保存配置文件内容,然后在mybatis配置文件中进行读取
在resource文件下新建db.properties文件

# Oracle 数据库驱动
jdbc.driverClass=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.1.xxx.xxx:1521:orcl
jdbc.username=orcl
jdbc.password=orcl

# Mysql数据库配置文件
#jdbc.driver = com.mysql.cj.jdbc.Driver
#jdbc.url = jdbc:mysql://192.1.xxx.xxx:3306/mybatis
#jdbc.username =user01
#jdbc.password =123456
2. 配置mybatis-config.xml

配置mybatis-config.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入外部properties文件 -->
<properties resource="com/gblfy/conf/db.properties"></properties>
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="com/gblfy/mapper/mapping/UserMapper.xml"/>
</mappers>

</configuration>
3. 加解密工具类

数据库密码加密
生产环境的数据库密码都为加密密码,需要在使用的时候,把加密密码解密成为明文
先创建数据库密码类

package com.gblfy.aes256.utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.Security;

/**
* AES加解密工具类
*
* @author gblfy
* @Date 2020-08-20
*/
@SuppressWarnings("unused")
public class AES256Utils {

/**
* 密钥算法 java6支持56位密钥,bouncycastle支持64位
*/
public static final String KEY_ALGORITHM = "AES";

/**
* 加密/解密算法/工作模式/填充方式
* <p>
* JAVA6 支持PKCS5PADDING填充方式 Bouncy castle支持PKCS7Padding填充方式
*/
public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";


/**
* 转换密钥
*
* @param key 二进制密钥
* @return Key 密钥
*/
public static Key toKey(String key) throws Exception {
// 实例化DES密钥
// 生成密钥
byte[] raw = key.getBytes("ASCII");
SecretKeySpec secretKey = new SecretKeySpec(raw, "AES");
// SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM);
return secretKey;
}

/**
* 加密数据
*
* @param data 待加密数据
* @param key 密钥
* @return byte[] 加密后的数据
*/
public static String encrypt(String data, String key) throws Exception {
// 还原密钥
Key k = toKey(key);
/**
* 实例化 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现
* Cipher.getInstance(CIPHER_ALGORITHM,"BC")
*/
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
// 初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
// 执行操作
byte[] encrypted = cipher.doFinal(data.getBytes());
String enc = new BASE64Encoder().encode(encrypted);
return enc;
}

/**
* 解密数据
*
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密后的数据
*/
public static String decrypt(String data, String key) throws Exception {
// 欢迎密钥
Key k = toKey(key);
/**
* 实例化使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现
* Cipher.getInstance(CIPHER_ALGORITHM,"BC")
*/
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);

// 执行操作
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, "utf-8");

return originalString;
}


public static void main(String[] args) throws UnsupportedEncodingException {

String data2 = "123456";
// 初始化密钥
String skey = "KSDF692EB704D3FCDCEAD9F55FE97EGB";
try {

// 信息加密
String decryptkey = AES256Utils.encrypt(data2, skey);
System.out.println("加密后的key值:" + decryptkey);

// 解密数据
String data = AES256Utils.decrypt(decryptkey, skey);
System.out.println("解密后的key值:" + data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 加解密依赖
<!--SHA256Hex加密-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.56</version>
</dependency>
5. 创建SqlSessionFactoryUtil类
package com.gblfy.util;

import com.gblfy.consts.BaseConst;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Properties;

/**
* @author gblfy
* 构建SqlSessionFactory
* 由于数据库连接是宝贵的,需要对数据库连接统一管理,所以使用单例进行管理
* 这里的单利使用的双重锁
* SqlSessionFactory为线程不安全类型需要加锁,确保同一时刻,只有一个线程可以使用该对象
*/
public class SqlSessionFactoryUtil {

/**
* SqlSessionFactory对象
*/
private static SqlSessionFactory sqlSessionFactory = null;

/**
* 类线程锁
*/
private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class;

/**
* 单例
*/
private SqlSessionFactoryUtil() {

}

/**
* @return SqlSessionFactory
* 初始化SqlSessionFactory对象
*/
public static SqlSessionFactory initSqlSessionFactory() {
// 获得输入流
InputStream cfgStream = null;
// 阅读流
Reader cfgReader = null;
InputStream proStream = null;
Reader proReader = null;
// 持久化属性集
Properties properties = null;
try {
// 配置文件流 我这里配置文件做了特殊处理
cfgStream = Resources.getResourceAsStream(BaseConst.MYBATIS_CONF);
#配置文件在resource目录下面采用这种方式
# cfgStream = Resources.getResourceAsStream("mybatis-config.xml");
// 获得阅读流
cfgReader = new InputStreamReader(cfgStream);
// 读入属性文件 我这里配置文件做了特殊处理
proStream = Resources.getResourceAsStream(BaseConst.MYBATIS_DB_CONF);
#配置文件在resource目录下面采用这种方式
#proStream = Resources.getResourceAsStream("db.properties");

proReader = new InputStreamReader(proStream);
// 持久化属性集
properties = new Properties();
// 流装载进入属性集合
properties.load(proReader);
// 获取当前系统ENV
String key = "ASDF692EB704D3FCDCEAD9F55FE97EGB";
// String key = System.getenv("DB_ENCRYPT_KEY");
// 进行解密
String encryptPwd = properties.getProperty("jdbc.password");
properties.setProperty("jdbc.password", AES256Utils.decrypt(encryptPwd, key));
// properties.setProperty("password", Decode.decryptDecode(properties.getProperty("jdbc.password"), key));
} catch (Exception e) {
e.printStackTrace();
}

if (sqlSessionFactory == null) {
synchronized (CLASS_LOCK) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties);
}
}
return sqlSessionFactory;
}

/**
* 打开SqlSession
*
* @return SqlSession
*/
public static SqlSession getSqlSession() {
// 判空处理
if (sqlSessionFactory == null) {
initSqlSessionFactory();
}
return sqlSessionFactory.openSession();
}

// /**
// * 获取SqlSession
// *
// * @return
// * @throws IOException
// */
// public static SqlSession getSqlSession() throws IOException {
// //mybatis的配置文件
// String resource = BaseConst.MYBATIS_CONF;
// //使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)
// InputStream is = Resources.getResourceAsStream(resource);
// //构建sqlSession的工厂
// SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
// return sessionFactory.openSession();
// }
public static void main(String[] args) {
String key = System.getenv("DB_ENCRYPT_KEY");
System.out.println("获取环境变量中的加密key: " + key);
}

}

注:如果配置文件都在resource目录下面,获取文件

6. db.properties加密后

接着,再次对密码进行加密,在读取的时候,对阅读流的结果集进行持久化设置
先对db.properties数据库密码进行加密
更改以后配置文件如下

# Oracle 数据库驱动
jdbc.driverClass=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.1.xxx.xxx:1521:orcl
jdbc.username=orcl
jdbc.password=15+fxnVIOd6h17zAg9vjEQ==

# Mysql数据库配置文件
#jdbc.driver = com.mysql.cj.jdbc.Driver
#jdbc.url = jdbc:mysql://192.1.xxx.xxx:3306/mybatis
#jdbc.username = user01
#jdbc.password = 15+fxnVIOd6h17zAg9vjEQ==
7. 常量类
package com.gblfy.consts;

public class BaseConst {

public static final String MYBATIS_CONF= "com/gblfy/conf/mybatis-conf.xml";
public static final String MYBATIS_DB_CONF= "com/gblfy/conf/db.properties";
public static final String DB_ENCRYPT_KEY= "PBDF692EB704D3FCDCEAD9F55FE87EGB";
public static final String DB_PWD_KEY= "jdbc.password";
}