MySQL连接配置文件密码加密及其在多种连接池上的应用

数据库 MySQL
为了安全,连接数据库的配置文件中,如密码等信息需要采用密文的形式存放。本文将给出多种连接池数据库密码密文存放的实现~

MySQL连接配置文件密码加密及其在多种连接池上的应用

为了安全,连接数据库的配置文件中,如密码等信息需要采用密文的形式存放。

本文将给出多种连接池数据库密码密文存放的实现~

如何配置数据库密码加密访问数据库?

将配置文件用户相关的信息(例如:密码)进行加密使其以密文形式存在,进行初始化连接池的时候进行解密操作,达到成功创建连接池的目的。

接下来,我们完成如下几个连接池采用数据库密文存储的实现:

  •     DBCP连接池
  •     C3P0连接池
  •     Druid连接池

DBCP连接池

数据库属性文件database.properties

配置数据库属性文件, 配置数据库连接的密码(jdbc.password)设置为加密后的值,该值可以采用AES、DES、3DES等对称加密方式实现,也可以采用RSA的加密算法存储~

 

  1. # jdbc.driverClassName 
  2. jdbc.driverClassName=com.mysql.jdbc.Driver 
  3.  
  4. Database URL 
  5. jdbc.url=jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull 
  6. jdbc.username=abc 
  7. jdbc.password=YpIADNvyi+/X2O33wS5E9SaEVKZgKuS70X8kgxgioEJ7+7KccS8aVmFIWndJ83NsUebDkb+w94HM3xCyjnjg4Q== 
  8.  
  9. Time to wait for an open connection before timing out 
  10. # (in milliseconds) 
  11. cpool.checkoutTimeout=5000 
  12.  
  13. Connection pool size 
  14. cpool.minPoolSize=10 
  15. cpool.maxPoolSize=50 
  16.  
  17. # How long to keep unused connections around(in seconds) 
  18. # Note: MySQL times out idle connections after 8 hours(28,800 seconds) 
  19. # so ensure this value is below MySQL idle timeout 
  20. cpool.maxIdleTime=25200 
  21.  
  22. # How long to hang on to excess unused connections after traffic spike 
  23. # (in seconds) 
  24. cpool.maxIdleTimeExcessConnections=1800 
  25.  
  26. # Acquiring new connections is slow, so eagerly retrieve extra connections 
  27. when current pool size is reached 
  28. cpool.acquireIncrement=10 

自定义CustomDataSource

如果采用DBCP连接池,那么,我们可以采用自定义连接池,继承org.apache.commons.dbcp.BasicDataSource,然后重写setPassword(String password)方法即可~

  1. import org.apache.commons.codec.binary.Base64; 
  2.  
  3. /** 
  4.  * @Type CustomDataSource.java 
  5.  * @Desc  
  6.  * @author wangmengjun 
  7.  * @date 2017年12月12日 下午8:50:49 
  8.  * @version  
  9.  */ 
  10. public class CustomDataSource extends org.apache.commons.dbcp.BasicDataSource { 
  11.  
  12.     public CustomDataSource() { 
  13.         super(); 
  14.     } 
  15.  
  16.     @Override 
  17.     public void setPassword(String password) { 
  18.         try { 
  19.             String decodePassword =  new String(Base64.decodeBase64(password.getBytes())); 
  20.             this.password =decodePassword; 
  21.         } catch (Exception e) { 
  22.         } 
  23.     } 
  24.  

上述自定义DataSource示例中,采用Base64来完成简单的加解密~

配置文件配置dataSource的地方,将org.apache.commons.dbcp.BasicDataSource改写成自定义连接池类名即可(如:com.xxx.datasource.CustomDataSource)~

  1. <bean id="dataSource" class="com.xxx.datasource.CustomDataSource" 
  2.         destroy-method="close"
  3.         <property name="driverClassName" value="${jdbc.driverClassName}" /> 
  4.         <property name="url" value="${jdbc.url}" /> 
  5.         <property name="username" value="${jdbc.username}" /> 
  6.         <property name="password" value="${jdbc.password}" /> 
  7.         <!-- 可同时连接的最大的连接数 --> 
  8.         <property name="maxActive" value="60" /> 
  9.         <!-- 最大的空闲的连接数 --> 
  10.         <property name="maxIdle" value="60" /> 
  11.         <!-- 最小的空闲的连接数,低于这个数量会被创建新的连接,默认为0 --> 
  12.         <property name="minIdle" value="5" /> 
  13.         <!-- 连接池启动时创建的初始化连接数量,默认值为0 --> 
  14.         <property name="initialSize" value="1" /> 
  15.         <!-- 等待连接超时时间,毫秒,默认为无限 --> 
  16.         <property name="maxWait" value="30000" /> 
  17.     </bean> 

经过上述几个步骤,就可以采用密文配置数据库密码。

C3P0连接池

数据库属性文件database.properties

属性配置文件内容和上述DBCP连接池示例中的一致~

如果采用的C3P0连接池,那么,我们要做的是在配置com.mchange.v2.c3p0.ComboPooledDataSource的地方,增加properties属性,编写一个PropertiesFactory类,实现password的解密操作即可~

  • 编写CustomDatasourcePropertiesFactory类
  1. import java.util.Properties; 
  2.  
  3. import org.apache.commons.codec.binary.Base64; 
  4. import org.slf4j.Logger; 
  5. import org.slf4j.LoggerFactory; 
  6.  
  7. /** 
  8.  * @Type CustomDatasourcePropertiesFactory.java 
  9.  * @Desc  
  10.  * @author wangmengjun 
  11.  * @date 2017年12月12日 下午9:11:06 
  12.  * @version  
  13.  */ 
  14. public class CustomDatasourcePropertiesFactory { 
  15.  
  16.     private static final String PASSWORD_PROPERTY = "password"
  17.  
  18.     private static final Logger logger = LoggerFactory 
  19.             .getLogger(CustomDatasourcePropertiesFactory.class); 
  20.  
  21.     public static Properties getProperties(String password) throws Exception { 
  22.         Properties properties = new Properties(); 
  23.         try { 
  24.             /** 
  25.              * 解密密码 
  26.              */ 
  27.             String decodePassword = new String(Base64.decodeBase64(password.getBytes())); 
  28.             properties.setProperty(PASSWORD_PROPERTY, decodePassword); 
  29.         } catch (Exception e) { 
  30.             logger.error("CustomDatasourcePropertiesFactory#getProperties" + e.getMessage(), e); 
  31.         } 
  32.         return properties; 
  33.     } 

采用Base64来完成密码密文解密。

  • 为ComboPooledDataSource配置名为properties的属性
  1. <property name="properties"
  2.             <bean class="com.xxx.datasource.CustomDatasourcePropertiesFactory" 
  3.                 factory-method="getProperties"
  4.                 <constructor-arg type="java.lang.String"
  5.                     <value>${jdbc.password}</value> 
  6.                 </constructor-arg> 
  7.             </bean> 
  8.         </property> 

完整示例如下:

  1. <!-- 配置数据源-C3PO --> 
  2.     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
  3.         destroy-method="close"
  4.         <property name="properties"
  5.             <bean class="com.xxx.datasource.CustomDatasourcePropertiesFactory" 
  6.                 factory-method="getProperties"
  7.                 <constructor-arg type="java.lang.String"
  8.                     <value>${jdbc.password}</value> 
  9.                 </constructor-arg> 
  10.             </bean> 
  11.         </property> 
  12.         <property name="driverClass" value="${jdbc.driverClassName}" /> 
  13.         <property name="jdbcUrl" value="${jdbc.url}" /> 
  14.         <property name="user" value="${jdbc.username}" /> 
  15.         <!-- <property name="password" value="${jdbc.password}" /> --> 
  16.         <property name="autoCommitOnClose" value="false" /> 
  17.         <property name="maxIdleTime" value="${cpool.maxIdleTime}" /> 
  18.         <property name="checkoutTimeout" value="${cpool.checkoutTimeout}" /> 
  19.         <property name="initialPoolSize" value="${cpool.minPoolSize}" /> 
  20.         <property name="minPoolSize" value="${cpool.minPoolSize}" /> 
  21.         <property name="maxPoolSize" value="${cpool.maxPoolSize}" /> 
  22.         <property name="acquireIncrement" value="${cpool.acquireIncrement}" /> 
  23.         <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}" /> 
  24.     </bean> 

Druid连接池

数据库连接属性文件

  1. username=abc 
  2. password=YpIADNvyi+/X2O33wS5E9SaEVKZgKuS70X8kgxgioEJ7+7KccS8aVmFIWndJ83NsUebDkb+w94HM3xCyjnjg4Q== 
  3. url=jdbc:mysql://127.0.0.1:3306/InIot?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull 
  4. driver=com.mysql.jdbc.Driver 
  5. initialSize=5 
  6. minIdle=5 
  7. maxActive=20 
  8. maxWait=60000 
  9. timeBetweenEvictionRunsMillis=60000 
  10. minEvictableIdleTimeMillis=30000 
  11. validationQuery=SELECT 1 
  12. testWhileIdle=true 
  13. testOnBorrow=true 
  14. testOnReturn=true 
  15. filters=stat,log4j 
  16. removeAbandoned=true 
  17. removeAbandonedTimeout=1200 
  18. logAbandoned=true 

实现密文密码配置

在Druid连接池中密文采用RSA的方式进行,com.alibaba.druid.filter.config.ConfigTools工具类提供了RSA的加解密功能,经过如下2个步骤,能成密文密码配置的功能~

  • 产生一个密文

采用com.alibaba.druid.filter.config.ConfigTools完成RSA的加解密功能

ConfigTools的部分代码如下:

  1. public class ConfigTools { 
  2.  
  3.     private static final String DEFAULT_PRIVATE_KEY_STRING = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAocbCrurZGbC5GArEHKlAfDSZi7gFBnd4yxOt0rwTqKBFzGyhtQLu5PRKjEiOXVa95aeIIBJ6OhC2f8FjqFUpawIDAQABAkAPejKaBYHrwUqUEEOe8lpnB6lBAsQIUFnQI/vXU4MV+MhIzW0BLVZCiarIQqUXeOhThVWXKFt8GxCykrrUsQ6BAiEA4vMVxEHBovz1di3aozzFvSMdsjTcYRRo82hS5Ru2/OECIQC2fAPoXixVTVY7bNMeuxCP4954ZkXp7fEPDINCjcQDywIgcc8XLkkPcs3Jxk7uYofaXaPbg39wuJpEmzPIxi3k0OECIGubmdpOnin3HuCP/bbjbJLNNoUdGiEmFL5hDI4UdwAdAiEAtcAwbm08bKN7pwwvyqaCBC//VnEWaq39DCzxr+Z2EIk="
  4.     public static final String DEFAULT_PUBLIC_KEY_STRING = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHGwq7q2RmwuRgKxBypQHw0mYu4BQZ3eMsTrdK8E6igRcxsobUC7uT0SoxIjl1WveWniCASejoQtn/BY6hVKWsCAwEAAQ=="
  5.  
  6.     public static void main(String[] args) throws Exception { 
  7.         String password = args[0]; 
  8.         String[] arr = genKeyPair(512); 
  9.         System.out.println("privateKey:" + arr[0]); 
  10.         System.out.println("publicKey:" + arr[1]); 
  11.         System.out.println("password:" + encrypt(arr[0], password)); 
  12.     } 
  13.  
  14.     public static String decrypt(String cipherText) throws Exception { 
  15.         return decrypt((String) null, cipherText); 
  16.     } 
  17.  
  18.     public static String decrypt(String publicKeyText, String cipherText) 
  19.             throws Exception { 
  20.         PublicKey publicKey = getPublicKey(publicKeyText); 
  21.  
  22.         return decrypt(publicKey, cipherText); 
  23.     } 
  24.  
  25. ... ...  
  26.  

测试一下:

  1. import com.alibaba.druid.filter.config.ConfigTools; 
  2.  
  3. /** 
  4.  * @Type ConfigToolsTest.java 
  5.  * @Desc  
  6.  * @author wangmengjun 
  7.  * @date 2017年12月12日 下午1:09:38 
  8.  * @version  
  9.  */ 
  10. public class ConfigToolsTest { 
  11.  
  12.     public static void main(String[] args) throws Exception { 
  13.        String password = "abc123123"
  14.        String encodePassword =  ConfigTools.encrypt(password); 
  15.        System.out.println("明文密码: " + encodePassword); 
  16.        System.out.println("密文密码: " + ConfigTools.decrypt(encodePassword)); 
  17.     } 

输出:

  1. 明文密码: TcrvCxmsd2588abZpfT8DE4C1GO3rbt6S99arh1yWJC/pGjhN3vzGN182j65Ei65M00PjR+uvMC/hN12t4CxHg== 
  2.  
  3. 密文密码: abc123123 

另外,也可以采用命令,获取RSA公钥、密钥和密码~

  1. java -cp druid-1.0.31.jar com.alibaba.druid.filter.config.ConfigTools you_password 

如:

  1. F:\>java -cp druid-1.0.31.jar com.alibaba.druid.filter.config.ConfigTools abc123123 
  2.  
  3. privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAzvPye2JYkSLqekOHPjNWdxYsfXP2XXAsJYR2Z1zukYlchouhvYvQhNrA9r7vxtvCFZKpWbAMC7YfKM4vvyz5DwIDAQABAkAgwlDR4yFt5/8B14qi9/Fp7GKigSawZ781OSCdAALrmm+9WrPsck9klZegUnUc5ewnjC3mBoqqd5aTrRH0EZtRAiEA9RfJ4yOjTEQtl2GXUWy2uP1evxyp8hbOxPYj1TDZDasCIQDYKaZrjySu7AJ9leScDGLmUBzhWX2FeXZ0IIMHEeq2LQIhAJA6TX2yrRfmTwX0Uf2CggxeXXENRxzFOyxAxFlig3g9AiAhuAWEu7R+MMSGsI4TpX777D1FDb+dxX+rx7KItMvHFQIgaHGt2T/Qw+qJ9+GIi9/qQkUhKUK59vDYFB5j0mmkJRc= 
  4.  
  5. publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM7z8ntiWJEi6npDhz4zVncWLH1z9l1wLCWEdmdc7pGJXIaLob2L0ITawPa+78bbwhWSqVmwDAu2HyjOL78s+Q8CAwEAAQ== 
  6.  
  7. password:zctG01uijEcWQ34N9ishfOkuQtMBucDApSeD+Jrg9qOitMavrrErhrQFeBkdlf4KI7b8YCUn2O6TWa6Z6fVQQg== 
  8. F:\>
  • 配置connectionProperties属性
  1. <!-- config.decrypt=true --> 
  2.         <property name="filters" value="config" /> 
  3.         <property name="connectionProperties" value="config.decrypt=true" /> 

详细的数据源配置如下:

  1. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
  2.         <property name="driverClassName" value="${driver}" /> 
  3.         <property name="url" value="${url}" /> 
  4.         <property name="username" value="${username}" /> 
  5.         <property name="password" value="${password}" /> 
  6.         <!-- config.decrypt=true --> 
  7.         <property name="filters" value="config" /> 
  8.         <property name="connectionProperties" value="config.decrypt=true" /> 
  9.         <!-- 初始化连接大小 --> 
  10.         <property name="initialSize" value="${initialSize}" /> 
  11.         <!-- 连接池最大使用连接数量 --> 
  12.         <property name="maxActive" value="${maxActive}" /> 
  13.         <!-- 连接池最大空闲 这个参数已经被弃用 --> 
  14.         <property name="maxIdle" value="${maxIdle}"></property> 
  15.         <!-- 连接池最小空闲 --> 
  16.         <property name="minIdle" value="${minIdle}"></property> 
  17.         <!-- 获取连接最大等待时间 --> 
  18.         <property name="maxWait" value="${maxWait}"></property> 
  19.         <property name="validationQuery" value="${validationQuery}" /> 
  20.         <property name="testWhileIdle" value="${testWhileIdle}" /> 
  21.         <property name="testOnBorrow" value="${testOnBorrow}" /> 
  22.         <property name="testOnReturn" value="${testOnReturn}" /> 
  23.         <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> 
  24.         <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /> 
  25.         <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> 
  26.         <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /> 
  27.         <!-- 关闭长时间不使用的连接 打开removeAbandoned功能 --> 
  28.         <property name="removeAbandoned" value="${removeAbandoned}" /> 
  29.         <!-- 1200秒,也就是20分钟 --> 
  30.         <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> 
  31.         <!-- 关闭abanded连接时输出错误日志 --> 
  32.         <property name="logAbandoned" value="${logAbandoned}" /> 
  33.     </bean> 

可以从Druid官网获取更多的信息。

【官网】https://github.com/alibaba/druid/wiki/使用ConfigFilter

至此,三种数据库连接池,包括DBCP、C3P0以及Druid的密码配置就完成了~

回顾一下:

如何配置数据库密码加密访问数据库 ?

将配置文件用户相关的信息(例如:密码)进行加密使其以密文形式存在,进行初始化连接池的时候进行解密操作,达到成功创建连接池的目的。

 

 

责任编辑:庞桂玉 来源: 王孟君的博客
相关推荐

2009-07-22 11:45:43

2010-05-17 16:38:08

MySQL 连接池

2011-05-13 09:34:51

TomcatMysql连接池

2011-06-01 13:54:10

MySQL

2009-07-09 17:36:44

JDBC连接池配置

2009-06-16 09:25:31

JBoss配置

2009-06-17 09:59:46

Hibernate 连

2009-06-17 16:22:45

Hibernate连接

2021-03-24 09:06:01

MySQL长连接短连接

2009-09-22 16:04:50

Hibernate连接

2010-05-21 09:48:30

java jsp to

2023-03-03 09:55:40

MySQL高可用

2009-05-18 17:16:50

2019-12-30 15:30:13

连接池请求PHP

2010-03-18 14:39:55

Python数据库连接

2010-06-12 13:04:03

MySQL连接池

2023-11-28 08:01:25

2010-11-08 16:46:57

2022-02-28 07:37:02

Java配置参数

2022-12-09 18:06:21

点赞
收藏

51CTO技术栈公众号