refactor ConfigFilter

This commit is contained in:
wenshao
2012-09-01 09:01:59 +08:00
parent b0a519e44f
commit eaf0ccb80b
3 changed files with 156 additions and 136 deletions
@@ -15,28 +15,20 @@
*/
package com.alibaba.druid.filter.config;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.X509EncodedKeySpec;
import java.sql.SQLException;
import java.util.Properties;
import javax.crypto.Cipher;
import com.alibaba.druid.filter.FilterAdapter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.proxy.jdbc.DataSourceProxy;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.Base64;
import com.alibaba.druid.util.JdbcUtils;
/**
@@ -50,7 +42,7 @@ import com.alibaba.druid.util.JdbcUtils;
* //启用config filter
* dataSource.setFilters("config");
* //使用RSA解密(使用默认密钥)
* dataSource.setConnectionPropertise("config.decrypt=RSA");
* dataSource.setConnectionPropertise("config.decrypt=true");
* dataSource.setPassword("加密的密文");
*
* [远程配置文件]
@@ -67,7 +59,7 @@ import com.alibaba.druid.util.JdbcUtils;
* <property name="password" value="加密的密文" />
* <!-- 其他的属性设置 -->
* <property name="filters" value="config" />
* <property name="connectionProperties" value="config.decrypt=RSA" />
* <property name="connectionProperties" value="config.decrypt=true" />
* </bean>
*
* [Spring的配置远程配置文件]
@@ -78,7 +70,7 @@ import com.alibaba.druid.util.JdbcUtils;
* </bean>
*
* [使用系统属性配置远程文件]
* java -Ddruid.config.file=file:/home/test/my.properties ...
* java -Ddruid.config.file=file:///home/test/my.properties ...
*
* 远程配置文件格式:
* 1. 其他的属性KEY请查看 @see com.alibaba.druid.pool.DruidDataSourceFactory
@@ -87,29 +79,26 @@ import com.alibaba.druid.util.JdbcUtils;
* config.file=http://xxxxx(http://开头或者file:开头)
*
* #RSA解密, Key不指定, 使用默认的
* config.decrypt=RSA
* config.decrypt=true
* config.decrypt.key=密钥字符串
* config.decrypt.keyFile=密钥文件路径
* config.decrypt.x509File=证书路径
*
* </pre>
*
* @author Jonas Yang
*/
public class ConfigFilter extends FilterAdapter {
private static Log LOG = LogFactory.getLog(ConfigFilter.class);
private static Log LOG = LogFactory.getLog(ConfigFilter.class);
public static final String CONFIG_FILE = "config.file";
public static final String CONFIG_FILE = "config.file";
public static final String CONFIG_DECRYPT = "config.decrypt";
public static final String CONFIG_KEY = "config.decrypt.key";
public static final String CONFIG_KEY_FILE = "config.decrypt.keyFile";
public static final String CONFIG_X509_FILE = "config.decrypt.x509File";
public static final String CONFIG_DECRYPT = "config.decrypt";
public static final String SYS_PROP_CONFIG_FILE = "druid.config.file";
public static final String KEY = "config.decrypt.key";
public static final String KEY_FILE = "config.decrypt.keyFile";
public static final String X509_FILE = "config.decrypt.x509File";
public static final String DEFAULT_PUBLIC_KEY_STRING = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHGwq7q2RmwuRgKxBypQHw0mYu4BQZ3eMsTrdK8E6igRcxsobUC7uT0SoxIjl1WveWniCASejoQtn/BY6hVKWsCAwEAAQ==";
public static final String SYS_PROP_CONFIG_FILE = "druid.config.file";
public ConfigFilter(){
}
@@ -202,10 +191,7 @@ public class ConfigFilter extends FilterAdapter {
}
PublicKey publicKey = getPublicKey(dataSource.getConnectProperties(), info);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
String passwordPlainText = decrypt(cipher, encryptedPassword);
String passwordPlainText = ConfigTools.decrypt(publicKey, encryptedPassword);
if (info != null) {
info.setProperty(DruidDataSourceFactory.PROP_PASSWORD, passwordPlainText);
@@ -217,110 +203,32 @@ public class ConfigFilter extends FilterAdapter {
}
}
protected String decrypt(Cipher cipher, String cipherString) throws Exception {
if (cipherString == null || cipherString.length() == 0) {
return cipherString;
}
byte[] cipherBytes = Base64.base64ToByteArray(cipherString);
byte[] plainBytes = cipher.doFinal(cipherBytes);
return new String(plainBytes);
}
public PublicKey getPublicKey(Properties connectinProperties, Properties configFileProperties) {
String key = connectinProperties.getProperty(KEY);
String publicKeyFile = connectinProperties.getProperty(KEY_FILE);
String x509File = connectinProperties.getProperty(X509_FILE);
String key = connectinProperties.getProperty(CONFIG_KEY);
String publicKeyFile = connectinProperties.getProperty(CONFIG_KEY_FILE);
String x509File = connectinProperties.getProperty(CONFIG_X509_FILE);
if (connectinProperties != null && (key == null || key.length() == 0)) {
key = connectinProperties.getProperty(KEY);
key = connectinProperties.getProperty(CONFIG_KEY);
}
if (connectinProperties != null && (publicKeyFile == null || publicKeyFile.length() == 0)) {
publicKeyFile = connectinProperties.getProperty(KEY_FILE);
publicKeyFile = connectinProperties.getProperty(CONFIG_KEY_FILE);
}
if (connectinProperties != null && (x509File == null || x509File.length() == 0)) {
x509File = connectinProperties.getProperty(X509_FILE);
x509File = connectinProperties.getProperty(CONFIG_X509_FILE);
}
if (publicKeyFile != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Decrypt by public key file");
}
return getPublicKeyByPublicKeyFile(publicKeyFile);
return ConfigTools.getPublicKeyByPublicKeyFile(publicKeyFile);
}
if (x509File != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Decrypt by X509 file");
}
return getPublicKeyByX509(x509File);
return ConfigTools.getPublicKeyByX509(x509File);
}
return getPublicKeyByString(key);
}
public PublicKey getPublicKeyByX509(String x509File) {
if (x509File == null || x509File.length() == 0) {
return getPublicKeyByString(null);
}
FileInputStream in = null;
try {
in = new FileInputStream(x509File);
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Certificate cer = factory.generateCertificate(in);
return cer.getPublicKey();
} catch (Exception e) {
throw new IllegalArgumentException("Failed to get public key", e);
} finally {
JdbcUtils.close(in);
}
}
public PublicKey getPublicKeyByPublicKeyFile(String publicKeyFile) {
if (publicKeyFile == null || publicKeyFile.length() == 0) {
return getPublicKeyByString(null);
}
FileInputStream in = null;
try {
in = new FileInputStream(publicKeyFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = 0;
byte[] b = new byte[512 / 8];
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
byte[] publicKeyBytes = out.toByteArray();
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(spec);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to get public key", e);
} finally {
JdbcUtils.close(in);
}
}
public PublicKey getPublicKeyByString(String publicKeyString) {
if (publicKeyString == null || publicKeyString.length() == 0) {
publicKeyString = DEFAULT_PUBLIC_KEY_STRING;
}
try {
byte[] publicKeyBytes = Base64.base64ToByteArray(publicKeyString);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(x509KeySpec);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to get public key", e);
}
return ConfigTools.getPublicKey(key);
}
public Properties loadConfig(String filePath) {
@@ -10,18 +10,22 @@ import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import com.alibaba.druid.util.Base64;
import com.alibaba.druid.util.JdbcUtils;
public class ConfigTools {
private static final String DEFAULT_PRIVATE_KEY_STRING = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAocbCrurZGbC5GArEHKlAfDSZi7gFBnd4yxOt0rwTqKBFzGyhtQLu5PRKjEiOXVa95aeIIBJ6OhC2f8FjqFUpawIDAQABAkAPejKaBYHrwUqUEEOe8lpnB6lBAsQIUFnQI/vXU4MV+MhIzW0BLVZCiarIQqUXeOhThVWXKFt8GxCykrrUsQ6BAiEA4vMVxEHBovz1di3aozzFvSMdsjTcYRRo82hS5Ru2/OECIQC2fAPoXixVTVY7bNMeuxCP4954ZkXp7fEPDINCjcQDywIgcc8XLkkPcs3Jxk7uYofaXaPbg39wuJpEmzPIxi3k0OECIGubmdpOnin3HuCP/bbjbJLNNoUdGiEmFL5hDI4UdwAdAiEAtcAwbm08bKN7pwwvyqaCBC//VnEWaq39DCzxr+Z2EIk=";
private static boolean isEnd = false;
public static final String DEFAULT_PUBLIC_KEY_STRING = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHGwq7q2RmwuRgKxBypQHw0mYu4BQZ3eMsTrdK8E6igRcxsobUC7uT0SoxIjl1WveWniCASejoQtn/BY6hVKWsCAwEAAQ==";
public static void main(String[] args) {
System.out.println("**************************************");
@@ -30,29 +34,111 @@ public class ConfigTools {
System.out.println("* *");
System.out.println("**************************************");
while (!isEnd) {
System.out.println();
System.out.println("RSA 选项: ");
System.out.println("1. 通过私钥加密");
System.out.println("2. 创建 RSA 密钥");
System.out.println("3. 退出");
System.out.println("");
System.out.println();
System.out.println("RSA 选项: ");
System.out.println("1. 通过私钥加密");
System.out.println("2. 创建 RSA 密钥");
System.out.println("3. 退出");
System.out.println("");
String input = System.console().readLine("[RSA]请输入选项: ");
input = input.toLowerCase();
String input = System.console().readLine("[RSA]请输入选项: ");
input = input.toLowerCase();
if ("1".equals(input)) {
encrypt();
} else if ("2".equals(input)) {
generateKeys();
} else if ("q".equals(input) || "3".equals(input)) {
System.exit(0);
} else {
System.err.println("不是一个合法的输入.");
}
if ("1".equals(input)) {
encrypt();
} else if ("2".equals(input)) {
generateKeys();
} else if ("q".equals(input) || "3".equals(input)) {
System.exit(0);
} else {
System.err.println("不是一个合法的输入.");
}
}
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);
}
public static PublicKey getPublicKeyByX509(String x509File) {
if (x509File == null || x509File.length() == 0) {
return ConfigTools.getPublicKey(null);
}
FileInputStream in = null;
try {
in = new FileInputStream(x509File);
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Certificate cer = factory.generateCertificate(in);
return cer.getPublicKey();
} catch (Exception e) {
throw new IllegalArgumentException("Failed to get public key", e);
} finally {
JdbcUtils.close(in);
}
}
public static PublicKey getPublicKey(String publicKeyText) {
if (publicKeyText == null || publicKeyText.length() == 0) {
publicKeyText = ConfigTools.DEFAULT_PUBLIC_KEY_STRING;
}
try {
byte[] publicKeyBytes = Base64.base64ToByteArray(publicKeyText);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(x509KeySpec);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to get public key", e);
}
}
public static PublicKey getPublicKeyByPublicKeyFile(String publicKeyFile) {
if (publicKeyFile == null || publicKeyFile.length() == 0) {
return ConfigTools.getPublicKey(null);
}
FileInputStream in = null;
try {
in = new FileInputStream(publicKeyFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = 0;
byte[] b = new byte[512 / 8];
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
byte[] publicKeyBytes = out.toByteArray();
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(spec);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to get public key", e);
} finally {
JdbcUtils.close(in);
}
}
public static String decrypt(PublicKey publicKey, String cipherText) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
if (cipherText == null || cipherText.length() == 0) {
return cipherText;
}
byte[] cipherBytes = Base64.base64ToByteArray(cipherText);
byte[] plainBytes = cipher.doFinal(cipherBytes);
return new String(plainBytes);
}
private static void encrypt() {
System.out.println("注意: 如果输入的不是该工具生成的私钥, 请转成PKCS#8格式, 使用下面命令");
@@ -82,7 +168,6 @@ public class ConfigTools {
byte[] encryptedBytes = cipher.doFinal(plainString.getBytes());
String encryptedString = Base64.byteArrayToBase64(encryptedBytes);
;
System.out.println("请记住以下的密文, 长度为[" + encryptedString.length() + "].");
System.out.println();
@@ -93,6 +178,32 @@ public class ConfigTools {
e.printStackTrace();
}
}
public static String encrypt(String plainText) throws Exception {
return encrypt((String) null, plainText);
}
public static String encrypt(String key, String plainText) throws Exception {
if (key == null) {
key = DEFAULT_PRIVATE_KEY_STRING;
}
byte[] keyBytes = Base64.base64ToByteArray(key);
return encrypt(keyBytes, plainText);
}
public static String encrypt(byte[] keyBytes, String plainText) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = factory.generatePrivate(spec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
String encryptedString = Base64.byteArrayToBase64(encryptedBytes);
return encryptedString;
}
private static byte[] getPrivateKeyFromFile(String filePath) throws IOException {
if (!new File(filePath).exists()) {
@@ -170,4 +281,5 @@ public class ConfigTools {
}
}
}
}
@@ -1,4 +1,4 @@
url=jdbc:mock:config-2
testOnBorrow=false
maxActive=12
password=TFxB6eJcgxE1hxOgiwOC/L7zWR/9vnSIfpggI2PTfcvvRhSnCGCPwI9n03fiJiLmRdnDU2/KaVTJYwz8zzkBqg==
password=ns2B+nJLNaoXgGakWqqsP6tWu8ZN25D1FncyKCTB/hNup8LW0g/66iGyrkDBHf9tgPJ8QtLz+upQSyin2g4flg==