Tomcat 10中如何避免JDBC数据源使用明文密码并实现加密解密
Tomcat 10 自定义数据源工厂实现JDBC密码加密解密操作步骤
1. 实现自定义数据源工厂与加解密工具类
加解密工具类示例
你可以选择对称加密算法(如AES、国密SM4等)实现加解密逻辑,示例采用AES算法,密钥可通过环境变量、JVM启动参数等安全方式读取,不要硬编码在代码中:
package com.yourpackage.util; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AesEncryptUtil { // 实际使用时不要硬编码密钥,可从系统环境变量或JVM参数获取 private static final String KEY = System.getenv("DB_ENCRYPT_KEY"); private static final String ALGORITHM = "AES"; // 加密方法,用于生成密文密码 public static String encrypt(String plainText) throws Exception { SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encrypted = cipher.doFinal(plainText.getBytes()); return Base64.getEncoder().encodeToString(encrypted); } // 解密方法,用于数据源工厂中解析密文 public static String decrypt(String cipherText) throws Exception { SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText)); return new String(decrypted); } }
自定义数据源工厂类示例
继承Tomcat JDBC连接池默认的org.apache.tomcat.jdbc.pool.DataSourceFactory,重写数据源创建逻辑,在创建连接前解密密码:
package com.yourpackage.factory; import com.yourpackage.util.AesEncryptUtil; import org.apache.tomcat.jdbc.pool.DataSourceFactory; import org.apache.tomcat.jdbc.pool.PoolConfiguration; import javax.sql.DataSource; import java.util.Properties; public class EncryptedDataSourceFactory extends DataSourceFactory { @Override public DataSource createDataSource(Properties properties) throws Exception { // 读取配置中的加密密码 String encryptedPwd = properties.getProperty("password"); if (encryptedPwd != null) { // 解密后重新设置到配置中 String plainPwd = AesEncryptUtil.decrypt(encryptedPwd); properties.setProperty("password", plainPwd); } return super.createDataSource(properties); } // 如果使用PoolConfiguration参数的重载方法,也需要同步重写 @Override protected DataSource createDataSource(PoolConfiguration poolConfig) throws Exception { String encryptedPwd = poolConfig.getPassword(); if (encryptedPwd != null) { String plainPwd = AesEncryptUtil.decrypt(encryptedPwd); poolConfig.setPassword(plainPwd); } return super.createDataSource(poolConfig); } }
如果你使用Tomcat默认的DBCP2连接池,只需将继承的父类替换为
org.apache.commons.dbcp2.BasicDataSourceFactory,解密逻辑完全一致。
2. 部署类文件到Tomcat类路径
将编译后的AesEncryptUtil、EncryptedDataSourceFactory以及所有依赖的第三方加密包全部放到${TOMCAT_HOME}/lib目录下,不要放在Web应用的WEB-INF/lib中,否则Tomcat启动加载server.xml时会找不到类。
3. 修改server.xml数据源配置
在原有数据源Resource配置中新增factory属性,值为自定义工厂的全类名,password填写加密后的密文即可:
<Resource name="jdbc/YourDB" auth="Container" type="javax.sql.DataSource" factory="com.yourpackage.factory.EncryptedDataSourceFactory" driverClassName="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8" username="your_db_user" password="这里填写AesEncryptUtil.encrypt(原始密码)生成的密文" maxTotal="100" maxIdle="30" maxWaitMillis="10000"/>
注意事项
- 加密密钥必须妥善保管,不要和密文、代码存储在同一位置,推荐使用环境变量、配置中心或硬件加密模块存储
- 配置完成后启动Tomcat,检查启动日志确认数据源初始化正常、数据库连接成功
- 若出现
ClassNotFoundException,优先检查自定义工厂类的全类名拼写是否正确、类文件是否已放入Tomcat的lib目录
内容的提问来源于stack exchange,提问作者Riddhi Patel
相关产品推荐
相关产品推荐

