Druid实现数据源加密(单数据源与多数据源类似)
阿里的Druid数据库连接池其实是支持用户名密码做加密处理的,有对应的callback配置,
官网中有相应介绍,详见:https://github.com/alibaba/druid/wiki/DruidDataSource配置属性列表
官网中只介绍了密码加密,根据源码发现用户名也是支持加密的,只是文档没有及时更新。
源码获取连接信息处理逻辑:

因此,可在项目中添加以下配置及对应的callBack处理类:
1、添加连接参数配置:
<!-- 密码解密处理类 --> <bean id="dbPasswordCallback" class="com.simple.test.DbPasswordCallback"> <property name="encPassword" value="#{app['jdbc.password']}" /> </bean> <!--用户名解密处理类 --> <bean id="dbNameCallback" class="com.simple.test.DbNameCallback"> <constructor-arg index="0" value="123123123" /> <property name="encUserName" value="#{app['jdbc.username']}" /> </bean> <!-- 数据源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="#{app['jdbc.url']}" /> <property name="username" value="#{app['jdbc.username']}" /> <property name="password" value="#{app['jdbc.password']}" /> <property name="filters" value="slf4j" /> <property name="maxActive" value="#{app['jdbc.maxActive']}" /> <property name="initialSize" value="#{app['jdbc.initialSize']}" /> <property name="minIdle" value="#{app['jdbc.minIdle']}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="#{app['jdbc.maxWait']}" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x'" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 通过connectProperties参数配置加密密钥 --> <property name="connectProperties"> <props> <prop key="appPrivateKeyFilePath">123123123</prop> </props> </property> <!-- 配置用户名、密码解密处理类 --> <property name="userCallback" ref="dbNameCallback" /> <property name="passwordCallback" ref="dbPasswordCallback" /> </bean>
2、添加相应的依赖
本帖使用的Jasypt加密,可以使用其他的加密算法,如AES等等。
<dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt</artifactId> <version>1.9.3</version> </dependency>
3、添加相应的解密处理类
/** * 用户名解密处理 */ public class DbNameCallback extends NameCallback { private static final Logger logger = LoggerFactory.getLogger(DbNameCallback.class); private String encUserName; public DbNameCallback(String prompt) { super(prompt); } public DbNameCallback(String prompt, String defaultName) { super(prompt, defaultName); } public String getEncUserName() { return encUserName; } public void setEncUserName(String encUserName) { this.encUserName = encUserName; } @Override public String getName() { // 获取配置参数中的密钥 String propertyPwd = getPrompt(); try { StandardPBEStringEncryptor decryptor = new StandardPBEStringEncryptor(); decryptor.setAlgorithm("PBEWithMD5AndDES"); decryptor.setPassword(propertyPwd); encUserName = encUserName.substring(4, encUserName.length()-1); return decryptor.decrypt(encUserName); } catch (Exception e) { logger.error("Druid ConfigTools.decrypt", e); } return ""; } }
/** * 密码解密处理类 */ public class DbPasswordCallback extends DruidPasswordCallback { private static final Logger logger = LoggerFactory.getLogger(DbPasswordCallback.class); private String encPassword; public String getEncPassword() { return encPassword; } public void setEncPassword(String encPassword) { this.encPassword = encPassword; } @Override public void setProperties(Properties properties){ super.setProperties(properties); // 获取配置参数中的密钥 String propertyPwd = properties.getProperty("appPrivateKeyFilePath"); try { StandardPBEStringEncryptor decryptor = new StandardPBEStringEncryptor(); decryptor.setAlgorithm("PBEWithMD5AndDES"); decryptor.setPassword(propertyPwd); encPassword = StringUtils.subString(encPassword, "ENC(", ")"); String decryptedText = decryptor.decrypt(encPassword); //String dbpassword = ConfigTools.decrypt(publickey, encryptionPassword); setPassword(decryptedText.toCharArray()); } catch (Exception e) { logger.error("Druid ConfigTools.decrypt", e); } } }
4、以下是本地生成加密串的方法,无需提交
public static void main(String[] args) { // 注意:加密密钥必须与生产环境一致 String encryptionPassword = "123123123"; StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm("PBEWithMD5AndDES"); encryptor.setPassword(encryptionPassword); String plainText = "test_name"; String encryptedText = encryptor.encrypt(plainText); System.out.println("加密后的文本: ENC(" + encryptedText + ")"); StandardPBEStringEncryptor decryptor = new StandardPBEStringEncryptor(); decryptor.setAlgorithm("PBEWithMD5AndDES"); decryptor.setPassword(encryptionPassword); String decryptedText = decryptor.decrypt(encryptedText); System.out.println("解密后的文本: " + decryptedText); }
至此,完美解决。

浙公网安备 33010602011771号