前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL连接配置文件密码加密及其在多种连接池上的应用

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

作者头像
孟君
发布2019-09-10 15:22:56
3.4K0
发布2019-09-10 15:22:56
举报

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

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

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

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

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

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

二、DBCP连接池

2.1 数据库属性文件database.properties

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

代码语言:javascript
复制
# jdbc.driverClassName
jdbc.driverClassName=com.mysql.jdbc.Driver

# Database URL
jdbc.url=jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
jdbc.username=abc
jdbc.password=YpIADNvyi+/X2O33wS5E9SaEVKZgKuS70X8kgxgioEJ7+7KccS8aVmFIWndJ83NsUebDkb+w94HM3xCyjnjg4Q==

# Time to wait for an open connection before timing out
# (in milliseconds)
cpool.checkoutTimeout=5000

# Connection pool size
cpool.minPoolSize=10
cpool.maxPoolSize=50

# How long to keep unused connections around(in seconds)
# Note: MySQL times out idle connections after 8 hours(28,800 seconds)
# so ensure this value is below MySQL idle timeout
cpool.maxIdleTime=25200

# How long to hang on to excess unused connections after traffic spike
# (in seconds)
cpool.maxIdleTimeExcessConnections=1800

# Acquiring new connections is slow, so eagerly retrieve extra connections
# when current pool size is reached
cpool.acquireIncrement=10

2.2 自定义CustomDataSource

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

代码语言:javascript
复制
import org.apache.commons.codec.binary.Base64;

/**
 * @Type CustomDataSource.java
 * @Desc 
 * @author wangmengjun
 * @date 2017年12月12日 下午8:50:49
 * @version 
 */
public class CustomDataSource extends org.apache.commons.dbcp.BasicDataSource {

    public CustomDataSource() {
        super();
    }

    @Override
    public void setPassword(String password) {
        try {
            String decodePassword =  new String(Base64.decodeBase64(password.getBytes()));
            this.password =decodePassword;
        } catch (Exception e) {
        }
    }

}

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

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

代码语言:javascript
复制
  <bean id="dataSource" class="com.xxx.datasource.CustomDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <!-- 可同时连接的最大的连接数 -->
    <property name="maxActive" value="60" />
    <!-- 最大的空闲的连接数 -->
    <property name="maxIdle" value="60" />
    <!-- 最小的空闲的连接数,低于这个数量会被创建新的连接,默认为0 -->
    <property name="minIdle" value="5" />
    <!-- 连接池启动时创建的初始化连接数量,默认值为0 -->
    <property name="initialSize" value="1" />
    <!-- 等待连接超时时间,毫秒,默认为无限 -->
    <property name="maxWait" value="30000" />
  </bean>

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

三、C3P0连接池

3.1 数据库属性文件database.properties

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

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

  • 编写CustomDatasourcePropertiesFactory类
代码语言:javascript
复制
import java.util.Properties;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Type CustomDatasourcePropertiesFactory.java
 * @Desc 
 * @author wangmengjun
 * @date 2017年12月12日 下午9:11:06
 * @version 
 */
public class CustomDatasourcePropertiesFactory {

    private static final String PASSWORD_PROPERTY = "password";

    private static final Logger logger = LoggerFactory
            .getLogger(CustomDatasourcePropertiesFactory.class);

    public static Properties getProperties(String password) throws Exception {
        Properties properties = new Properties();
        try {
            /**
             * 解密密码
             */
            String decodePassword = new String(Base64.decodeBase64(password.getBytes()));
            properties.setProperty(PASSWORD_PROPERTY, decodePassword);
        } catch (Exception e) {
            logger.error("CustomDatasourcePropertiesFactory#getProperties" + e.getMessage(), e);
        }
        return properties;
    }
}

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

  • 为ComboPooledDataSource配置名为properties的属性
代码语言:javascript
复制
    <property name="properties">
      <bean class="com.xxx.datasource.CustomDatasourcePropertiesFactory"
        factory-method="getProperties">
        <constructor-arg type="java.lang.String">
          <value>${jdbc.password}</value>
        </constructor-arg>
      </bean>
    </property>

完整示例如下:

代码语言:javascript
复制
<!-- 配置数据源-C3PO -->
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close">
    <property name="properties">
      <bean class="com.xxx.datasource.CustomDatasourcePropertiesFactory"
        factory-method="getProperties">
        <constructor-arg type="java.lang.String">
          <value>${jdbc.password}</value>
        </constructor-arg>
      </bean>
    </property>
    <property name="driverClass" value="${jdbc.driverClassName}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <!-- <property name="password" value="${jdbc.password}" /> -->
    <property name="autoCommitOnClose" value="false" />
    <property name="maxIdleTime" value="${cpool.maxIdleTime}" />
    <property name="checkoutTimeout" value="${cpool.checkoutTimeout}" />
    <property name="initialPoolSize" value="${cpool.minPoolSize}" />
    <property name="minPoolSize" value="${cpool.minPoolSize}" />
    <property name="maxPoolSize" value="${cpool.maxPoolSize}" />
    <property name="acquireIncrement" value="${cpool.acquireIncrement}" />
    <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}" />
  </bean>

四、Druid连接池

4.1 数据库连接属性文件

代码语言:javascript
复制
username=abc
password=YpIADNvyi+/X2O33wS5E9SaEVKZgKuS70X8kgxgioEJ7+7KccS8aVmFIWndJ83NsUebDkb+w94HM3xCyjnjg4Q==
url=jdbc:mysql://127.0.0.1:3306/InIot?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
driver=com.mysql.jdbc.Driver
initialSize=5
minIdle=5
maxActive=20
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=30000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=true
testOnReturn=true
filters=stat,log4j
removeAbandoned=true
removeAbandonedTimeout=1200
logAbandoned=true

4.2 实现密文密码配置

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

  • 产生一个密文

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

ConfigTools的部分代码如下:

代码语言:javascript
复制
public class ConfigTools {

  private static final String DEFAULT_PRIVATE_KEY_STRING = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAocbCrurZGbC5GArEHKlAfDSZi7gFBnd4yxOt0rwTqKBFzGyhtQLu5PRKjEiOXVa95aeIIBJ6OhC2f8FjqFUpawIDAQABAkAPejKaBYHrwUqUEEOe8lpnB6lBAsQIUFnQI/vXU4MV+MhIzW0BLVZCiarIQqUXeOhThVWXKFt8GxCykrrUsQ6BAiEA4vMVxEHBovz1di3aozzFvSMdsjTcYRRo82hS5Ru2/OECIQC2fAPoXixVTVY7bNMeuxCP4954ZkXp7fEPDINCjcQDywIgcc8XLkkPcs3Jxk7uYofaXaPbg39wuJpEmzPIxi3k0OECIGubmdpOnin3HuCP/bbjbJLNNoUdGiEmFL5hDI4UdwAdAiEAtcAwbm08bKN7pwwvyqaCBC//VnEWaq39DCzxr+Z2EIk=";
  public static final String DEFAULT_PUBLIC_KEY_STRING = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHGwq7q2RmwuRgKxBypQHw0mYu4BQZ3eMsTrdK8E6igRcxsobUC7uT0SoxIjl1WveWniCASejoQtn/BY6hVKWsCAwEAAQ==";

  public static void main(String[] args) throws Exception {
        String password = args[0];
        String[] arr = genKeyPair(512);
        System.out.println("privateKey:" + arr[0]);
        System.out.println("publicKey:" + arr[1]);
        System.out.println("password:" + encrypt(arr[0], password));
  }

  public static String decrypt(String cipherText) throws Exception {
    return decrypt((String) null, cipherText);
  }

  public static String decrypt(String publicKeyText, String cipherText)
      throws Exception {
    PublicKey publicKey = getPublicKey(publicKeyText);

    return decrypt(publicKey, cipherText);
  }

... ... 

}

测试一下:

代码语言:javascript
复制
import com.alibaba.druid.filter.config.ConfigTools;

/**
 * @Type ConfigToolsTest.java
 * @Desc 
 * @author wangmengjun
 * @date 2017年12月12日 下午1:09:38
 * @version 
 */
public class ConfigToolsTest {

    public static void main(String[] args) throws Exception {
       String password = "abc123123";
       String encodePassword =  ConfigTools.encrypt(password);
       System.out.println("明文密码: " + encodePassword);
       System.out.println("密文密码: " + ConfigTools.decrypt(encodePassword));
    }
}

输出:

代码语言:javascript
复制
明文密码: TcrvCxmsd2588abZpfT8DE4C1GO3rbt6S99arh1yWJC/pGjhN3vzGN182j65Ei65M00PjR+uvMC/hN12t4CxHg==
密文密码: abc123123

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

代码语言:javascript
复制
java -cp druid-1.0.31.jar com.alibaba.druid.filter.config.ConfigTools you_password

如:

代码语言:javascript
复制
F:\>java -cp druid-1.0.31.jar com.alibaba.druid.filter.config.ConfigTools abc123123
privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAzvPye2JYkSLqekOHPjNWdxYsfXP2XXAsJYR2Z1zukYlchouhvYvQhNrA9r7vxtvCFZKpWbAMC7YfKM4vvyz5DwIDAQABAkAgwlDR4yFt5/8B14qi9/Fp7GKigSawZ781OSCdAALrmm+9WrPsck9klZegUnUc5ewnjC3mBoqqd5aTrRH0EZtRAiEA9RfJ4yOjTEQtl2GXUWy2uP1evxyp8hbOxPYj1TDZDasCIQDYKaZrjySu7AJ9leScDGLmUBzhWX2FeXZ0IIMHEeq2LQIhAJA6TX2yrRfmTwX0Uf2CggxeXXENRxzFOyxAxFlig3g9AiAhuAWEu7R+MMSGsI4TpX777D1FDb+dxX+rx7KItMvHFQIgaHGt2T/Qw+qJ9+GIi9/qQkUhKUK59vDYFB5j0mmkJRc=
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM7z8ntiWJEi6npDhz4zVncWLH1z9l1wLCWEdmdc7pGJXIaLob2L0ITawPa+78bbwhWSqVmwDAu2HyjOL78s+Q8CAwEAAQ==
password:zctG01uijEcWQ34N9ishfOkuQtMBucDApSeD+Jrg9qOitMavrrErhrQFeBkdlf4KI7b8YCUn2O6TWa6Z6fVQQg==

F:\>
  • 配置connectionProperties属性
代码语言:javascript
复制
  <!-- config.decrypt=true -->
    <property name="filters" value="config" />
    <property name="connectionProperties" value="config.decrypt=true" />

详细的数据源配置如下:

代码语言:javascript
复制
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
    <!-- config.decrypt=true -->
    <property name="filters" value="config" />
    <property name="connectionProperties" value="config.decrypt=true" />
    <!-- 初始化连接大小 -->
    <property name="initialSize" value="${initialSize}" />
    <!-- 连接池最大使用连接数量 -->
    <property name="maxActive" value="${maxActive}" />
    <!-- 连接池最大空闲 这个参数已经被弃用 -->
    <property name="maxIdle" value="${maxIdle}"></property>
    <!-- 连接池最小空闲 -->
    <property name="minIdle" value="${minIdle}"></property>
    <!-- 获取连接最大等待时间 -->
    <property name="maxWait" value="${maxWait}"></property>
    <property name="validationQuery" value="${validationQuery}" />
    <property name="testWhileIdle" value="${testWhileIdle}" />
    <property name="testOnBorrow" value="${testOnBorrow}" />
    <property name="testOnReturn" value="${testOnReturn}" />
    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
    <!-- 关闭长时间不使用的连接 打开removeAbandoned功能 -->
    <property name="removeAbandoned" value="${removeAbandoned}" />
    <!-- 1200秒,也就是20分钟 -->
    <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
    <!-- 关闭abanded连接时输出错误日志 -->
    <property name="logAbandoned" value="${logAbandoned}" />
  </bean>

可以从Druid官网获取更多的信息。 【官网】https://github.com/alibaba/druid/wiki/使用ConfigFilter

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

回顾一下:如何配置数据库密码加密访问数据库 ?

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、如何配置数据库密码加密访问数据库?
  • 二、DBCP连接池
    • 2.1 数据库属性文件database.properties
      • 2.2 自定义CustomDataSource
      • 三、C3P0连接池
        • 3.1 数据库属性文件database.properties
        • 四、Druid连接池
          • 4.1 数据库连接属性文件
            • 4.2 实现密文密码配置
            相关产品与服务
            数据库
            云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档