关闭

Druid连接池自定义数据库密码加解密的实现

标签: Druid数据库密码加密
927人阅读 评论(0) 收藏 举报
分类:
1.Druid的功能

1、替换DBCPC3P0Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。

2、可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。

3数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiverDruidDataSource都支持PasswordCallback

4SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-LoggingLog4jJdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。

5、扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。

其中第三条说出了本博客的一个目的,详细过程如下:

1、首先配置Druid的数据库连接池

    <!--数据源加密操作-->
    <bean id="dbPasswordCallback" class="com.xuliugen.db.config.DBPasswordCallback" lazy-init="true"/>

    <bean id="statFilter" class="com.alibaba.druid.filter.stat.StatFilter" lazy-init="true">
        <property name="logSlowSql" value="true"/>
        <property name="mergeSql" value="true"/>
    </bean>
    <!-- 数据库连接 -->
    <bean id="readDataSource" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close" init-method="init" lazy-init="true">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url1}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="${initialSize}"/>
        <!-- 连接池最大数量 -->
        <property name="maxActive" value="${maxActive}"/>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="${minIdle}"/>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="${maxWait}"/>
        <!-- -->
        <property name="defaultReadOnly" value="true"/>
        <property name="proxyFilters">
            <list>
                <ref bean="statFilter"/>
            </list>
        </property>
        <property name="filters" value="${druid.filters}"/>
        <property name="connectionProperties" value="password=${password}"/>
        <property name="passwordCallback" ref="dbPasswordCallback"/>
        <property name="testWhileIdle" value="true"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
        <property name="validationQuery" value="SELECT 'x'"/>
        <property name="timeBetweenLogStatsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}"/>
    </bean>

其中要注意的是:

 <bean id="dbPasswordCallback" class="com.xuliugen.db.config.DBPasswordCallback" lazy-init="true"/>
 <property name="passwordCallback" ref="dbPasswordCallback"/>

2.创建DruidPasswordCallback的子类如下:

这里的DBPasswordCallback 是继承com.alibaba.druid.util.DruidPasswordCallback 的,重写的是DruidPasswordCallback 的setProperties方法,在setProperties方法中使用了setPassword(password.toCharArray());这个方法,setPassword是DruidPasswordCallback 的父类中的一个方法。

这里写图片描述

一个代码追踪过程:

这里写图片描述

package com.xuliugen.db.config;

import com.alibaba.druid.util.DruidPasswordCallback;
import org.apache.commons.lang3.StringUtils;

import java.util.Properties;

/**
 * 数据库密码回调解密
 */
@SuppressWarnings("serial")
public class DBPasswordCallback extends DruidPasswordCallback {

    public void setProperties(Properties properties) {
        super.setProperties(properties);
        String pwd = properties.getProperty("password");
        if (StringUtils.isNotBlank(pwd)) {
            try {
                //这里的password是将jdbc.properties配置得到的密码进行解密之后的值
                //所以这里的代码是将密码进行解密
                //TODO 将pwd进行解密;
                String password =  加密Util.解密(pwd); 
                setPassword(password.toCharArray());
            } catch (Exception e) {
                setPassword(pwd.toCharArray());
            }
        }
    }

    // 请使用该方法加密后,把密文写入classpath:/config/jdbc.properties
    public static void main(String[] args) {
        System.out.println(SecurityUtil.encryptDes("", key));
    }
}

其中PasswordCallbackjavax.security.auth.callback包下面的,底层安全服务实例化一个PasswordCallback并将其传递给CallbackHandlerhandle方法,以获取密码信息。

3.在jdbc.properties存放自己加密之后的信息

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username=buzhidao

#回调DBPasswordCallback解密,这里的密码是你加密之后的密码!!!
password=yYEtaRoo3QHpKaW我是加密之后的密码哦

#定义初始连接数
initialSize=20
#定义最大连接数
maxActive=40
#定义最大空闲
maxIdle=20
#定义最小空闲
minIdle=1
#定义最长等待时间
maxWait=60000

注意:23过程中密码的设置要确定,加密、解密的最初始密码是要对应的。

4、设置自定义的DruidPasswordCallback

在自己的spring配置文件中加入下边的一句bean配置:

<!--数据源加密操作 这里的class就是滴2步中自己创建的-->
<bean id="dbPasswordCallback" class="com.xuliugen.db.config.DBPasswordCallback" lazy-init="true"/>

另外还可以直接继承自Spring提供的PropertyPlaceholderConfigurer,摘录别人一段代码大家参考一下:

public class DecryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer{
    /**
     * 重写父类方法,解密指定属性名对应的属性值
     */
    @Override
    protected String convertProperty(String propertyName,String propertyValue){
        if(isEncryptPropertyVal(propertyName)){
            return DesUtils.getDecryptString(propertyValue);//调用解密方法
        }else{
            return propertyValue;
        }
    }
    /**
     * 判断属性值是否需要解密,这里我约定需要解密的属性名用encrypt开头
     * @param propertyName
     * @return
     */
    private boolean isEncryptPropertyVal(String propertyName){
        if(propertyName.startsWith("encrypt")){
            return true;
        }else{
            return false;
        }
    }
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场