mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
refactor ConfigFilter
This commit is contained in:
@@ -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==
|
||||
Reference in New Issue
Block a user