如何快速实现Tomcat数据库连接池数据库密码加密和解密呢?

在Tomcat服务器使用当中,我们经常会碰到各种错误原因和稀奇古怪的问题,就当最简单的“Tomcat数据库连接池数据库密码加密”来说吧,碰到这种问题该怎么解决呢?我们先看一段加密的Java工具类:

package com.vajra.security.encrypt;  
  
import java.io.IOException;  
import java.io.UnsupportedEncodingException;  
import java.security.InvalidAlgorithmParameterException;  
import java.security.InvalidKeyException;  
import java.security.NoSuchAlgorithmException;  
import java.security.spec.AlgorithmParameterSpec;  
import java.security.spec.InvalidKeySpecException;  
  
import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.NoSuchPaddingException;  
import javax.crypto.SecretKey;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.PBEKeySpec;  
import javax.crypto.spec.PBEParameterSpec;  
  
import sun.misc.BASE64Decoder;  
import sun.misc.BASE64Encoder;  
  
//Java加密工具类操作,@auther http://www.23tiyan.com
public class CipherEncrypter {  
    Cipher ecipher;  
    Cipher dcipher;  
    byte[] salt = { -87, -101, -56, 50, 86, 53, -29, 3 };  
  
    int iterationCount = 19;  
    private static CipherEncrypter cipherEncrypter;  
  
    private CipherEncrypter(String passPhrase) {  
        try {  
            PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray());  
            SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES")  
                    .generateSecret(keySpec);  
            this.ecipher = Cipher.getInstance(key.getAlgorithm());  
            this.dcipher = Cipher.getInstance(key.getAlgorithm());  
  
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(this.salt,  
                    this.iterationCount);  
  
            this.ecipher.init(1, key, paramSpec);  
            this.dcipher.init(2, key, paramSpec);  
        } catch (InvalidAlgorithmParameterException localInvalidAlgorithmParameterException) {  
        } catch (InvalidKeySpecException localInvalidKeySpecException) {  
        } catch (NoSuchPaddingException localNoSuchPaddingException) {  
        } catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {  
        } catch (InvalidKeyException localInvalidKeyException) {  
        }  
    }  
  
    private CipherEncrypter() {  
        this("sfpay");  
    }  
  
    public static CipherEncrypter getInstance() {  
        if (cipherEncrypter == null) {  
            cipherEncrypter = new CipherEncrypter();  
        }  
        return cipherEncrypter;  
    }  
  
    public static String encrypt(String str) {  
        try {  
            byte[] utf8 = str.getBytes("UTF8");  
            byte[] enc = getInstance().ecipher.doFinal(utf8);  
            return new BASE64Encoder().encode(enc);  
        } catch (BadPaddingException localBadPaddingException) {  
        } catch (IllegalBlockSizeException localIllegalBlockSizeException) {  
        } catch (UnsupportedEncodingException localUnsupportedEncodingException) {  
        } catch (Exception localException) {  
        }  
        return null;  
    }  
  
    public static String decrypt(String str) {  
        try {  
            byte[] dec = new BASE64Decoder().decodeBuffer(str);  
  
            byte[] utf8 = getInstance().dcipher.doFinal(dec);  
  
            return new String(utf8, "UTF8");  
        } catch (BadPaddingException localBadPaddingException) {  
        } catch (IllegalBlockSizeException localIllegalBlockSizeException) {  
        } catch (UnsupportedEncodingException localUnsupportedEncodingException) {  
        } catch (IOException localIOException) {  
        }  
        return null;  
    }  
  
    public static void main(String[] args) {  
        if (args.length != 1)  
            return;  
        System.out.println("encrypted string:" + encrypt(args[0]));  
    }  
}

而且要知道,在整个运行流程当中,必不可少的就是Factory中实现数据库密码解密方法:

package com.vajra.security.datasource;  
  
import java.io.ByteArrayInputStream;  
import java.sql.SQLException;  
import java.util.Collections;  
import java.util.Enumeration;  
import java.util.Hashtable;  
import java.util.Properties;  
import java.util.StringTokenizer;  
  
import javax.naming.Context;  
import javax.naming.Name;  
import javax.naming.RefAddr;  
import javax.naming.Reference;  
import javax.sql.DataSource;  
  
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;  
import org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory;  
  
import com.vajra.security.encrypt.CipherEncrypter;  
  
//数据库配置链接,@auther http://www.23tuzi.com
@SuppressWarnings("rawtypes")  
public class VajraBasicDataSourceFactory extends BasicDataSourceFactory {  
  
    protected static final String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";  
    protected static final String PROP_DEFAULTREADONLY = "defaultReadOnly";  
    protected static final String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";  
    protected static final String PROP_DEFAULTCATALOG = "defaultCatalog";  
    protected static final String PROP_DRIVERCLASSNAME = "driverClassName";  
    protected static final String PROP_MAXACTIVE = "maxActive";  
    protected static final String PROP_MAXIDLE = "maxIdle";  
    protected static final String PROP_MINIDLE = "minIdle";  
    protected static final String PROP_INITIALSIZE = "initialSize";  
    protected static final String PROP_MAXWAIT = "maxWait";  
    protected static final String PROP_TESTONBORROW = "testOnBorrow";  
    protected static final String PROP_TESTONRETURN = "testOnReturn";  
    protected static final String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";  
    protected static final String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";  
    protected static final String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";  
    protected static final String PROP_TESTWHILEIDLE = "testWhileIdle";  
    protected static final String PROP_PASSWORD = "password";  
    protected static final String PROP_URL = "url";  
    protected static final String PROP_USERNAME = "username";  
    protected static final String PROP_VALIDATIONQUERY = "validationQuery";  
    protected static final String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";  
    protected static final String PROP_INITCONNECTIONSQLS = "initConnectionSqls";  
    protected static final String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";  
    protected static final String PROP_REMOVEABANDONED = "removeAbandoned";  
    protected static final String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";  
    protected static final String PROP_LOGABANDONED = "logAbandoned";  
    protected static final String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";  
    protected static final String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";  
    protected static final String PROP_CONNECTIONPROPERTIES = "connectionProperties";  
    protected static final String[] ALL_PROPERTIES = { "defaultAutoCommit",  
            "defaultReadOnly", "defaultTransactionIsolation", "defaultCatalog",  
            "driverClassName", "maxActive", "maxIdle", "minIdle",  
            "initialSize", "maxWait", "testOnBorrow", "testOnReturn",  
            "timeBetweenEvictionRunsMillis", "numTestsPerEvictionRun",  
            "minEvictableIdleTimeMillis", "testWhileIdle", "password", "url",  
            "username", "validationQuery", "validationQueryTimeout",  
            "initConnectionSqls", "accessToUnderlyingConnectionAllowed",  
            "removeAbandoned", "removeAbandonedTimeout", "logAbandoned",  
            "poolPreparedStatements", "maxOpenPreparedStatements",  
            "connectionProperties" };  
  
    public Object getObjectInstance(Object obj, Name name, Context nameCtx,  
            Hashtable environment) throws Exception {  
        if ((obj == null) || (!(obj instanceof Reference))) {  
            return null;  
        }  
        Reference ref = (Reference) obj;  
        if (!"javax.sql.DataSource".equals(ref.getClassName())) {  
            return null;  
        }  
  
        Properties properties = new Properties();  
        for (int i = 0; i < ALL_PROPERTIES.length; i++) {  
            String propertyName = ALL_PROPERTIES[i];  
            RefAddr ra = ref.get(propertyName);  
            if (ra != null) {  
                String propertyValue = ra.getContent().toString();  
                properties.setProperty(propertyName, propertyValue);  
            }  
        }  
  
        return createDataSource(properties);  
    }  
  
//数据库链接,@auther http://www.23tiyan.com
    public static DataSource createDataSource(Properties properties)  
            throws Exception {  
        final BasicDataSource dataSource = new BasicDataSource();  
        String value = null;  
  
        value = properties.getProperty("defaultAutoCommit");  
        if (value != null) {  
            dataSource.setDefaultAutoCommit(Boolean.valueOf(value)  
                    .booleanValue());  
        }  
  
        value = properties.getProperty("defaultReadOnly");  
        if (value != null) {  
            dataSource  
                    .setDefaultReadOnly(Boolean.valueOf(value).booleanValue());  
        }  
  
        value = properties.getProperty("defaultTransactionIsolation");  
        if (value != null) {  
            int level = -1;  
            if ("NONE".equalsIgnoreCase(value)) {  
                level = 0;  
            } else if ("READ_COMMITTED".equalsIgnoreCase(value)) {  
                level = 2;  
            } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {  
                level = 1;  
            } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {  
                level = 4;  
            } else if ("SERIALIZABLE".equalsIgnoreCase(value))  
                level = 8;  
            else {  
                try {  
                    level = Integer.parseInt(value);  
                } catch (NumberFormatException e) {  
                    System.err  
                            .println("Could not parse defaultTransactionIsolation: "  
                                    + value);  
                    System.err  
                            .println("WARNING: defaultTransactionIsolation not set");  
                    System.err  
                            .println("using default value of database driver");  
  
                    level = -1;  
                }  
            }  
            dataSource.setDefaultTransactionIsolation(level);  
        }  
  
        value = properties.getProperty("defaultCatalog");  
        if (value != null) {  
            dataSource.setDefaultCatalog(value);  
        }  
  
        value = properties.getProperty("driverClassName");  
        if (value != null) {  
            dataSource.setDriverClassName(value);  
        }  
  
        value = properties.getProperty("maxActive");  
        if (value != null) {  
            dataSource.setMaxActive(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("maxIdle");  
        if (value != null) {  
            dataSource.setMaxIdle(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("minIdle");  
        if (value != null) {  
            dataSource.setMinIdle(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("initialSize");  
        if (value != null) {  
            dataSource.setInitialSize(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("maxWait");  
        if (value != null) {  
            dataSource.setMaxWait(Long.parseLong(value));  
        }  
  
        value = properties.getProperty("testOnBorrow");  
        if (value != null) {  
            dataSource.setTestOnBorrow(Boolean.valueOf(value).booleanValue());  
        }  
  
        value = properties.getProperty("testOnReturn");  
        if (value != null) {  
            dataSource.setTestOnReturn(Boolean.valueOf(value).booleanValue());  
        }  
  
        value = properties.getProperty("timeBetweenEvictionRunsMillis");  
        if (value != null) {  
            dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(value));  
        }  
  
        value = properties.getProperty("numTestsPerEvictionRun");  
        if (value != null) {  
            dataSource.setNumTestsPerEvictionRun(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("minEvictableIdleTimeMillis");  
        if (value != null) {  
            dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(value));  
        }  
  
        value = properties.getProperty("testWhileIdle");  
        if (value != null) {  
            dataSource.setTestWhileIdle(Boolean.valueOf(value).booleanValue());  
        }  
  
        value = properties.getProperty("password");  
        if (value != null) {  
            dataSource.setPassword(CipherEncrypter.decrypt(value.trim()));  
        }  
  
        value = properties.getProperty("url");  
        if (value != null) {  
            dataSource.setUrl(value);  
        }  
  
        value = properties.getProperty("username");  
        if (value != null) {  
            dataSource.setUsername(value.trim());  
        }  
  
        value = properties.getProperty("validationQuery");  
        if (value != null) {  
            dataSource.setValidationQuery(value);  
        }  
  
        value = properties.getProperty("validationQueryTimeout");  
        if (value != null) {  
            dataSource.setValidationQueryTimeout(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("accessToUnderlyingConnectionAllowed");  
        if (value != null) {  
            dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(  
                    value).booleanValue());  
        }  
  
        value = properties.getProperty("removeAbandoned");  
        if (value != null) {  
            dataSource  
                    .setRemoveAbandoned(Boolean.valueOf(value).booleanValue());  
        }  
  
        value = properties.getProperty("removeAbandonedTimeout");  
        if (value != null) {  
            dataSource.setRemoveAbandonedTimeout(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("logAbandoned");  
        if (value != null) {  
            dataSource.setLogAbandoned(Boolean.valueOf(value).booleanValue());  
        }  
  
        value = properties.getProperty("poolPreparedStatements");  
        if (value != null) {  
            dataSource.setPoolPreparedStatements(Boolean.valueOf(value)  
                    .booleanValue());  
        }  
  
        value = properties.getProperty("maxOpenPreparedStatements");  
        if (value != null) {  
            dataSource.setMaxOpenPreparedStatements(Integer.parseInt(value));  
        }  
  
        value = properties.getProperty("initConnectionSqls");  
        if (value != null) {  
            StringTokenizer tokenizer = new StringTokenizer(value, ";");  
            dataSource.setConnectionInitSqls(Collections.list(tokenizer));  
        }  
  
        value = properties.getProperty("connectionProperties");  
        if (value != null) {  
            Properties p = getProperties(value);  
            Enumeration e = p.propertyNames();  
            while (e.hasMoreElements()) {  
                String propertyName = (String) e.nextElement();  
                dataSource.addConnectionProperty(propertyName,  
                        p.getProperty(propertyName));  
            }  
  
        }  
  
        if (dataSource.getInitialSize() > 0) {  
            dataSource.getLogWriter();  
        }  
  
        Runtime.getRuntime().addShutdownHook(new Thread() {  
            public void run() {  
                try {  
                    dataSource.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            }  
        });  
  
        return dataSource;  
    }  
  
    protected static Properties getProperties(String propText) throws Exception {  
        Properties p = new Properties();  
        if (propText != null) {  
            p.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes()));  
        }  
        return p;  
    }  
  
}

这个时候,我们可以将以上两个类打包(vajra-dbsecure.jar),并指定一个Main入口类,再tomcat全局数据源中使用加密后的数据库密码就可以恢复了。

  

 如何快速实现Tomcat数据库连接池数据库密码加密的方法也就能够轻易的完成了!

你可能感兴趣的:(JAVA服务器端技术)