Tomcat数据源连接池加密

lqs1920 22天前 ⋅ 133 阅读

我们在使用Tomcat数据库连接池的时候都是明文存储数据库用户名和密码的,例如:

<Resource name="ODS" type="javax.sql.DataSource"
 driverClassName="oracle.jdbc.driver.OracleDriver"
 url="jdbc:oracle:thin:@192.168.1.1:1521:dbid"
 username="oracle"
 password="oracle"
 maxIdle="4"
 maxActive="6"
 maxWait="5000" />

如果我们不想让数据库的密码暴露在web容器中怎么办呢?写一个类继承org.apache.commons.dbcp.BasicDataSourceFactory,然后指定factory=”*.EncryptedDataSourceFactory”为你的自定义类,下面是相关代码:

package net.uni.ap.jdbc;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;

public class EncryptedDataSourceFactory extends BasicDataSourceFactory {

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

    private final String decryptKey = "填写自己的key";

    public Object getObjectInstance(Object obj, Name name, Context nameCtx,Hashtable environment) throws Exception {
        if (obj instanceof Reference) {
            //对用户名和密码进行解密
            setUsername((Reference) obj);
            setPassword((Reference) obj);
        }
        return super.getObjectInstance(obj, name, nameCtx, environment);
    }

    private void setUsername(Reference ref) throws Exception {
        findDecryptAndReplace("username", ref);
    }

    private void setPassword(Reference ref) throws Exception {
        findDecryptAndReplace("password", ref);
    }

    private void findDecryptAndReplace(String refType, Reference ref) throws Exception {
        int idx = find(refType, ref);
        String decrypted = decrypt(idx, ref);
        replace(idx, refType, decrypted, ref);
    }

    private void replace(int idx, String refType, String newValue, Reference ref) throws Exception {
        ref.remove(idx);
        ref.add(idx, new StringRefAddr(refType, newValue));
    }

    private String decrypt(int idx, Reference ref) throws Exception {
        //解密前
        String initContent = ref.get(idx).getContent().toString();
        //解密后
        String decryptContent =  AESDecrypt.decryptPassword(initContent,decryptKey);
        logger.debug("initContent={},decryptContent={}",initContent,decryptContent);
        return decryptContent;
    }

    private int find(String addrType, Reference ref) throws Exception {
        Enumeration enu = ref.getAll();
        for (int i = 0; enu.hasMoreElements(); i++) {
            RefAddr addr = (RefAddr) enu.nextElement();
            if (addr.getType().compareTo(addrType) == 0) {
                return i;
            }
        }
        throw new Exception("The \"" + addrType
                + "\" name/value pair was not found"
                + " in the Reference object. The reference Object is" + " "
                + ref.toString());
    }


最后tomcat数据源中的username和password改为加密后的值,factory为EncryptedDataSourceFactory路径就大功告成了:

<Context path="">
 <Resource name="ODS" type="javax.sql.DataSource"
 driverClassName="oracle.jdbc.driver.OracleDriver"
 factory="net.uni.ap.jdbc.EncryptedDataSourceFactory"
 url="jdbc:oracle:thin:@192.168.1.1:1521:sid"
 username="C65BD76C4CED33C446B289F64CAFACC5"
 password="C65BD76C4CED33C446B289F64CAFACC5"
 maxIdle="4"
 maxActive="6"
 maxWait="5000" />
</Context>
我有话说:

全部评论: 0