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,23 +15,28 @@
|
||||
*/
|
||||
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.filter.config.security.decrypter.DecryptException;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.Decrypter;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.DecrypterFactory;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.SensitiveParameters;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -88,144 +93,236 @@ import com.alibaba.druid.util.JdbcUtils;
|
||||
* 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_DECRYPT = "config.decrypt";
|
||||
|
||||
public static final String SYS_PROP_CONFIG_FILE = "druid.config.file";
|
||||
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 ConfigFilter(){
|
||||
}
|
||||
|
||||
public void init(DataSourceProxy dataSourceProxy) {
|
||||
if (!(dataSourceProxy instanceof DruidDataSource)) {
|
||||
log.error("ConfigLoader only support DruidDataSource");
|
||||
LOG.error("ConfigLoader only support DruidDataSource");
|
||||
}
|
||||
|
||||
Properties info = null;
|
||||
DruidDataSource dataSource = (DruidDataSource) dataSourceProxy;
|
||||
Properties connectinProperties = dataSource.getConnectProperties();
|
||||
|
||||
// 获取远程配置文件
|
||||
String configFile = connectinProperties.getProperty(CONFIG_FILE);
|
||||
|
||||
// 如果系统参数有指定
|
||||
if (configFile == null) {
|
||||
configFile = System.getProperty(SYS_PROP_CONFIG_FILE);
|
||||
}
|
||||
|
||||
if (configFile != null && configFile.length() > 0) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Config file will be load from [" + configFile + "].");
|
||||
}
|
||||
|
||||
info = loadConfig(configFile);
|
||||
|
||||
if (info == null) {
|
||||
throw new IllegalArgumentException("Cannot load remote config file from the [config.file=" + configFile
|
||||
+ "].");
|
||||
}
|
||||
} else {
|
||||
info = new Properties();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("No remote config file.");
|
||||
}
|
||||
}
|
||||
Properties configFileProperties = loadPropertyFromConfigFile(connectinProperties);
|
||||
|
||||
// 判断是否需要解密,如果需要就进行解密行动
|
||||
String decrypterId = info.getProperty(CONFIG_DECRYPT);
|
||||
boolean isRemotedSecurityConfig = true;
|
||||
boolean decrypt = isDecrypt(connectinProperties, configFileProperties);
|
||||
|
||||
if (decrypterId == null) {
|
||||
decrypterId = connectinProperties.getProperty(CONFIG_DECRYPT);
|
||||
isRemotedSecurityConfig = false;
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Get decrypt method " + decrypterId + " from local config.");
|
||||
}
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Get decrypt method " + decrypterId + " from remote config.");
|
||||
}
|
||||
}
|
||||
|
||||
if (decrypterId != null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Use [" + decrypterId + "] to decrypt sensitive parameters.");
|
||||
}
|
||||
|
||||
try {
|
||||
Decrypter decrypter = DecrypterFactory.getDecrypter(decrypterId);
|
||||
if (decrypter == null) {
|
||||
throw new IllegalArgumentException("Druid doesn't support the decrypter [config.decrypt="
|
||||
+ decrypterId + "].");
|
||||
}
|
||||
|
||||
Properties securityInfo = isRemotedSecurityConfig ? info : connectinProperties;
|
||||
|
||||
SensitiveParameters originalParameter = getSensitiveParameters(dataSource, info);
|
||||
SensitiveParameters parameters = decrypter.decrypt(originalParameter, securityInfo);
|
||||
|
||||
info.setProperty(DruidDataSourceFactory.PROP_URL, parameters.getUrl());
|
||||
info.setProperty(DruidDataSourceFactory.PROP_USERNAME, parameters.getUsername());
|
||||
info.setProperty(DruidDataSourceFactory.PROP_PASSWORD, parameters.getPassword());
|
||||
} catch (DecryptException e) {
|
||||
throw new IllegalArgumentException("Failed to decrypt.", e);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("No decrypt.");
|
||||
}
|
||||
}
|
||||
|
||||
// 没有任何配置
|
||||
if (info.size() == 0) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("No config.");
|
||||
if (configFileProperties == null) {
|
||||
if (decrypt) {
|
||||
decrypt(dataSource, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (decrypt) {
|
||||
decrypt(dataSource, configFileProperties);
|
||||
}
|
||||
|
||||
try {
|
||||
DruidDataSourceFactory.config(dataSource, info);
|
||||
DruidDataSourceFactory.config(dataSource, configFileProperties);
|
||||
} catch (SQLException e) {
|
||||
throw new IllegalArgumentException("Config DataSource error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果配置文件中没有值, 就取默认值
|
||||
*
|
||||
* @param dataSource
|
||||
* @param info
|
||||
* @return
|
||||
*/
|
||||
SensitiveParameters getSensitiveParameters(DruidDataSource dataSource, Properties info) {
|
||||
String username = info.getProperty(DruidDataSourceFactory.PROP_USERNAME);
|
||||
String password = info.getProperty(DruidDataSourceFactory.PROP_PASSWORD);
|
||||
String url = info.getProperty(DruidDataSourceFactory.PROP_URL);
|
||||
public boolean isDecrypt(Properties connectinProperties, Properties configFileProperties) {
|
||||
boolean decrypt = false;
|
||||
|
||||
if (username == null) {
|
||||
username = dataSource.getUsername();
|
||||
String decrypterId = connectinProperties.getProperty(CONFIG_DECRYPT);
|
||||
if (configFileProperties != null && (decrypterId == null || decrypterId.length() == 0)) {
|
||||
decrypterId = configFileProperties.getProperty(CONFIG_DECRYPT);
|
||||
}
|
||||
|
||||
if (password == null) {
|
||||
password = dataSource.getPassword();
|
||||
if ("true".equals(decrypterId)) {
|
||||
decrypt = true;
|
||||
}
|
||||
|
||||
if (url == null) {
|
||||
url = dataSource.getUrl();
|
||||
}
|
||||
|
||||
return new SensitiveParameters(url, username, password);
|
||||
return decrypt;
|
||||
}
|
||||
|
||||
|
||||
Properties loadPropertyFromConfigFile(Properties connectinProperties) {
|
||||
String configFile = connectinProperties.getProperty(CONFIG_FILE);
|
||||
|
||||
if (configFile == null) {
|
||||
configFile = System.getProperty(SYS_PROP_CONFIG_FILE);
|
||||
}
|
||||
|
||||
if (configFile != null && configFile.length() > 0) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("DruidDataSource Config File load from : " + configFile);
|
||||
}
|
||||
|
||||
Properties info = loadConfig(configFile);
|
||||
|
||||
if (info == null) {
|
||||
throw new IllegalArgumentException("Cannot load remote config file from the [config.file=" + configFile
|
||||
+ "].");
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void decrypt(DruidDataSource dataSource, Properties info) {
|
||||
|
||||
try {
|
||||
String encryptedPassword = null;
|
||||
if (info != null) {
|
||||
encryptedPassword = info.getProperty(DruidDataSourceFactory.PROP_PASSWORD);
|
||||
}
|
||||
|
||||
if (encryptedPassword == null || encryptedPassword.length() == 0) {
|
||||
encryptedPassword = dataSource.getConnectProperties().getProperty(DruidDataSourceFactory.PROP_PASSWORD);
|
||||
}
|
||||
|
||||
if (encryptedPassword == null || encryptedPassword.length() == 0) {
|
||||
encryptedPassword = dataSource.getPassword();
|
||||
}
|
||||
|
||||
PublicKey publicKey = getPublicKey(dataSource.getConnectProperties(), info);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
String passwordPlainText = decrypt(cipher, encryptedPassword);
|
||||
|
||||
if (info != null) {
|
||||
info.setProperty(DruidDataSourceFactory.PROP_PASSWORD, passwordPlainText);
|
||||
} else {
|
||||
dataSource.setPassword(passwordPlainText);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to decrypt.", e);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (connectinProperties != null && (key == null || key.length() == 0)) {
|
||||
key = connectinProperties.getProperty(KEY);
|
||||
}
|
||||
|
||||
if (connectinProperties != null && (publicKeyFile == null || publicKeyFile.length() == 0)) {
|
||||
publicKeyFile = connectinProperties.getProperty(KEY_FILE);
|
||||
}
|
||||
|
||||
if (connectinProperties != null && (x509File == null || x509File.length() == 0)) {
|
||||
x509File = connectinProperties.getProperty(X509_FILE);
|
||||
}
|
||||
|
||||
if (publicKeyFile != null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Decrypt by public key file");
|
||||
}
|
||||
return getPublicKeyByPublicKeyFile(publicKeyFile);
|
||||
}
|
||||
|
||||
if (x509File != null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Decrypt by X509 file");
|
||||
}
|
||||
return 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);
|
||||
}
|
||||
}
|
||||
|
||||
public Properties loadConfig(String filePath) {
|
||||
Properties properties = new Properties();
|
||||
|
||||
@@ -249,7 +346,7 @@ public class ConfigFilter extends FilterAdapter {
|
||||
}
|
||||
|
||||
if (inStream == null) {
|
||||
log.error("load config file error, file : " + filePath);
|
||||
LOG.error("load config file error, file : " + filePath);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -261,7 +358,7 @@ public class ConfigFilter extends FilterAdapter {
|
||||
|
||||
return properties;
|
||||
} catch (Exception ex) {
|
||||
log.error("load config file error, file : " + filePath, ex);
|
||||
LOG.error("load config file error, file : " + filePath, ex);
|
||||
return null;
|
||||
} finally {
|
||||
JdbcUtils.close(inStream);
|
||||
|
||||
+51
-38
@@ -1,51 +1,64 @@
|
||||
package com.alibaba.druid.filter.config.security.tool;
|
||||
package com.alibaba.druid.filter.config;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import com.alibaba.druid.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class RsaAction implements Action {
|
||||
public class ConfigTools {
|
||||
|
||||
private static final String DEFAULT_PRIVATE_KEY_STRING = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAocbCrurZGbC5GArEHKlAfDSZi7gFBnd4yxOt0rwTqKBFzGyhtQLu5PRKjEiOXVa95aeIIBJ6OhC2f8FjqFUpawIDAQABAkAPejKaBYHrwUqUEEOe8lpnB6lBAsQIUFnQI/vXU4MV+MhIzW0BLVZCiarIQqUXeOhThVWXKFt8GxCykrrUsQ6BAiEA4vMVxEHBovz1di3aozzFvSMdsjTcYRRo82hS5Ru2/OECIQC2fAPoXixVTVY7bNMeuxCP4954ZkXp7fEPDINCjcQDywIgcc8XLkkPcs3Jxk7uYofaXaPbg39wuJpEmzPIxi3k0OECIGubmdpOnin3HuCP/bbjbJLNNoUdGiEmFL5hDI4UdwAdAiEAtcAwbm08bKN7pwwvyqaCBC//VnEWaq39DCzxr+Z2EIk=";
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "RSA";
|
||||
}
|
||||
private static boolean isEnd = false;
|
||||
|
||||
public void execute() {
|
||||
help();
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
System.out.println("**************************************");
|
||||
System.out.println("* *");
|
||||
System.out.println("* Druid 加密工具 *");
|
||||
System.out.println("* *");
|
||||
System.out.println("**************************************");
|
||||
|
||||
private void help() {
|
||||
System.out.println();
|
||||
System.out.println("RSA 选项: ");
|
||||
System.out.println("1. 通过私钥加密");
|
||||
System.out.println("2. 创建 RSA 密钥");
|
||||
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("");
|
||||
|
||||
String input = System.console().readLine("[RSA]请输入选项: ");
|
||||
String input = System.console().readLine("[RSA]请输入选项: ");
|
||||
input = input.toLowerCase();
|
||||
|
||||
if ("1".equals(input)) {
|
||||
encrypt();
|
||||
} else if ("2".equals(input)) {
|
||||
generateKeys();
|
||||
} 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("不是一个合法的输入.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void encrypt() {
|
||||
|
||||
private static void encrypt() {
|
||||
System.out.println("注意: 如果输入的不是该工具生成的私钥, 请转成PKCS#8格式, 使用下面命令");
|
||||
System.out.println("openssl pkcs8 -topk8 -inform PEM -outform DER -in 原来的Key -nocrypt > 输出文件");
|
||||
String filePath = System.console().readLine("[RSA]请输入私钥文件路径[如果直接回车将使用默认私钥]: ");
|
||||
|
||||
|
||||
byte[] key = null;
|
||||
if (filePath == null || filePath.length() == 0) {
|
||||
key = Base64.base64ToByteArray(DEFAULT_PRIVATE_KEY_STRING);
|
||||
@@ -68,7 +81,8 @@ public class RsaAction implements Action {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
|
||||
byte[] encryptedBytes = cipher.doFinal(plainString.getBytes());
|
||||
String encryptedString = Base64.byteArrayToBase64(encryptedBytes);;
|
||||
String encryptedString = Base64.byteArrayToBase64(encryptedBytes);
|
||||
;
|
||||
|
||||
System.out.println("请记住以下的密文, 长度为[" + encryptedString.length() + "].");
|
||||
System.out.println();
|
||||
@@ -80,7 +94,7 @@ public class RsaAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getPrivateKeyFromFile(String filePath) throws IOException {
|
||||
private static byte[] getPrivateKeyFromFile(String filePath) throws IOException {
|
||||
if (!new File(filePath).exists()) {
|
||||
System.err.println("文件不存在[" + filePath + "]");
|
||||
}
|
||||
@@ -89,7 +103,7 @@ public class RsaAction implements Action {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(filePath);
|
||||
byte[] b = new byte[512/8];
|
||||
byte[] b = new byte[512 / 8];
|
||||
int len = 0;
|
||||
while ((len = in.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
@@ -106,7 +120,7 @@ public class RsaAction implements Action {
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private void generateKeys() {
|
||||
private static void generateKeys() {
|
||||
System.out.println();
|
||||
System.out.println("[RSA]请选择密钥长度: \n1. 512 \n2. 1024 \n3. 2048");
|
||||
String keySizeString = System.console().readLine("[RSA]请输入选项: ");
|
||||
@@ -145,7 +159,7 @@ public class RsaAction implements Action {
|
||||
|
||||
}
|
||||
|
||||
private void saveKey(Key key, String path) throws Exception {
|
||||
private static void saveKey(Key key, String path) throws Exception {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(path);
|
||||
@@ -156,5 +170,4 @@ public class RsaAction implements Action {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.filter.config.security.decrypter;
|
||||
|
||||
import com.alibaba.druid.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
/**
|
||||
* 加密抽象类
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public abstract class AbstractDecrypter implements Decrypter {
|
||||
|
||||
public final static String KEY = "config.decrypt.key";
|
||||
|
||||
/**
|
||||
* 传入密文, 返回明文
|
||||
* @param cipher 解密器
|
||||
* @param cipherString 密文
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.filter.config.security.decrypter;
|
||||
|
||||
/**
|
||||
* 加密出错
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class DecryptException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DecryptException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DecryptException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public DecryptException(String s, Throwable throwable) {
|
||||
super(s, throwable);
|
||||
}
|
||||
|
||||
public DecryptException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.filter.config.security.decrypter;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 解密敏感参数
|
||||
* [代码例子]
|
||||
*
|
||||
* DruidDataSource dataSource = new DruidDataSource();
|
||||
* //设置DataSource的其他参数
|
||||
* dataSource.setFilters("config");
|
||||
* dataSource.setUsername("test");
|
||||
* dataSource.setPassword("加密的密码");
|
||||
* dataSource.setConnectionProperties("config.decrypt=RSA");
|
||||
*
|
||||
* [下面是Spring的配置]
|
||||
*
|
||||
* <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
|
||||
* <property name="url" value="${jdbc_url}" />
|
||||
* <property name="username" value="${jdbc_user}" />
|
||||
* <property name="password" value="${jdbc_password}" />
|
||||
* <b><property name="filters" value="config" /></b>
|
||||
* <b><property name="connectionProperties" value="config.decrypt=RSA" /></b>
|
||||
* </bean>
|
||||
*
|
||||
* </pre>
|
||||
* <br/>
|
||||
* <b>默认下, Druid 已经实现了RSA加解密. RSA 密文必须是通过Druid Tool的加密工具生成的</b>
|
||||
* <b>获取默认解密方式可以通过 DecrypterFactory.getDecrypter(String id)</b>
|
||||
* <br/>
|
||||
* <b>使用加密工具: java -cp druid-x.x.x.jar com.alibaba.druid.filter.config.security.tool.Main</b>
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public interface Decrypter {
|
||||
|
||||
/**
|
||||
* 标识符
|
||||
* @return
|
||||
*/
|
||||
public String getId();
|
||||
|
||||
/**
|
||||
* 返回一个解密后的(明文)参数
|
||||
* @param parameters 密文参数
|
||||
* @return
|
||||
* @throws DecryptException 解密失败会抛出该异常
|
||||
*/
|
||||
public SensitiveParameters decrypt(SensitiveParameters parameters, Properties info) throws DecryptException;
|
||||
}
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.filter.config.security.decrypter;
|
||||
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 通过 ID 获取解密器
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class DecrypterFactory {
|
||||
|
||||
private static Log log = LogFactory.getLog(DecrypterFactory.class);
|
||||
|
||||
private static ConcurrentHashMap<String, Decrypter> decrypters = new ConcurrentHashMap<String, Decrypter>();
|
||||
|
||||
static {
|
||||
RsaDecrypter rsa = new RsaDecrypter();
|
||||
decrypters.put(rsa.getId(), rsa);
|
||||
}
|
||||
|
||||
private DecrypterFactory() {}
|
||||
|
||||
|
||||
// static void initDecrypters(String resource, ClassLoader classLoader) {
|
||||
// if (resource == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// InputStream inStream = null;
|
||||
//
|
||||
// try {
|
||||
// inStream = classLoader.getResourceAsStream(resource);
|
||||
// if (inStream == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// Properties p = new Properties();
|
||||
// p.load(inStream);
|
||||
//
|
||||
// for (String key : p.stringPropertyNames()) {
|
||||
// String clazzName = p.getProperty(key);
|
||||
// Class clazz = classLoader.loadClass(clazzName);
|
||||
// Decrypter decrypter = (Decrypter) clazz.newInstance();
|
||||
//
|
||||
// addDecrypter(decrypter);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// log.warn("Fail to init config loaders.", e);
|
||||
// } finally {
|
||||
// JdbcUtils.close(inStream);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 通过 ID 获取解密器, 如果没有找到, 返回 <code>null</code>
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static Decrypter getDecrypter(String id) {
|
||||
return decrypters.get(id);
|
||||
}
|
||||
|
||||
public static void addDecrypter(Decrypter decrypter) {
|
||||
Decrypter oldDecrypter = decrypters.putIfAbsent(decrypter.getId(), decrypter);
|
||||
if (oldDecrypter != null) {
|
||||
log.warn("Replace decrypter [" + decrypter.getId() + ", " + oldDecrypter.getClass() + "] with [" + decrypter.getClass() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public static Decrypter[] getDecrypters() {
|
||||
return decrypters.values().toArray(new Decrypter[0]);
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.filter.config.security.decrypter;
|
||||
|
||||
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;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
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.util.Properties;
|
||||
|
||||
/**
|
||||
* RSA 解密器, 支持证书
|
||||
*/
|
||||
public class RsaDecrypter extends AbstractDecrypter {
|
||||
|
||||
private static Log log = LogFactory.getLog(RsaDecrypter.class);
|
||||
|
||||
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 String getId() {
|
||||
return "RSA";
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 密钥 放在 <code>Properties</code> 参数中,
|
||||
* 如果是密钥字符串, key 是 config.decrypt.key
|
||||
* 如果是密钥文件, key 是 config.decrypt.keyFile
|
||||
* 如果是证书文件, key 是 config.decrypt.x509File
|
||||
*
|
||||
* 如果不指定密钥, 将使用默认密钥
|
||||
* </pre>
|
||||
*
|
||||
* @param parameters 密文参数
|
||||
* @param info
|
||||
* @return
|
||||
* @throws DecryptException
|
||||
*/
|
||||
public SensitiveParameters decrypt(SensitiveParameters parameters, Properties info) throws DecryptException {
|
||||
PublicKey publicKey = getPublicKey(info);
|
||||
return decrypt(parameters, publicKey);
|
||||
}
|
||||
|
||||
protected SensitiveParameters decrypt(SensitiveParameters parameters, PublicKey publicKey) throws DecryptException {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
String passwordPlainText = decrypt(cipher, parameters.getPassword());
|
||||
|
||||
return new SensitiveParameters(parameters.getUrl(), parameters.getUsername(), passwordPlainText);
|
||||
} catch (DecryptException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new DecryptException("Failed to decrypt parameters", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过指定
|
||||
*
|
||||
* @param info
|
||||
* @return
|
||||
*/
|
||||
public PublicKey getPublicKey(Properties info) {
|
||||
String key = null;
|
||||
String publicKeyFile = null;
|
||||
String x509File = null;
|
||||
|
||||
if (info != null) {
|
||||
key = info.getProperty(KEY);
|
||||
publicKeyFile = info.getProperty(KEY_FILE);
|
||||
x509File = info.getProperty(X509_FILE);
|
||||
}
|
||||
|
||||
if (publicKeyFile != null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Decrypt by public key file");
|
||||
}
|
||||
return getPublicKeyByPublicKeyFile(publicKeyFile);
|
||||
}
|
||||
|
||||
if (x509File != null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Decrypt by X509 file");
|
||||
}
|
||||
return getPublicKeyByX509(x509File);
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Decrypt by public key string");
|
||||
}
|
||||
|
||||
return getPublicKeyByString(key);
|
||||
}
|
||||
|
||||
public PublicKey getPublicKeyByString(String publicKeyString) {
|
||||
if (publicKeyString == null || publicKeyString.length() == 0) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Decrypt by default key");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.filter.config.security.decrypter;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 存放, 数据库的关键参数:URL, 用户名, 密码
|
||||
* 如果存放的是明文, 请尽可能缩短实例的作用域
|
||||
* </pre>
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class SensitiveParameters {
|
||||
private transient final String url;
|
||||
|
||||
private transient final String username;
|
||||
|
||||
private transient final String password;
|
||||
|
||||
public SensitiveParameters(String url, String username, String password) {
|
||||
this.url = url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.alibaba.druid.filter.config.security.tool;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public interface Action {
|
||||
|
||||
public String getId();
|
||||
|
||||
public void execute();
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.alibaba.druid.filter.config.security.tool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class HelpAction implements Action {
|
||||
|
||||
private List<ActionDesc> list = new ArrayList<ActionDesc>();
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "HELP";
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
System.out.println();
|
||||
for (ActionDesc desc : list) {
|
||||
System.out.println(desc.getKey() + ". " + desc.getAction().getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void addAction(String key, Action action) {
|
||||
this.list.add(new ActionDesc(key, action));
|
||||
}
|
||||
|
||||
public Action getAction(String key) {
|
||||
for (ActionDesc desc : list) {
|
||||
if (desc.getKey().equals(key)) {
|
||||
return desc.getAction();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ActionDesc {
|
||||
private final String key;
|
||||
private final Action action;
|
||||
|
||||
public ActionDesc(String key, Action action) {
|
||||
this.key = key;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.alibaba.druid.filter.config.security.tool;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Druid 提供的加密工具. 如下运行
|
||||
*
|
||||
* <b>java -cp druid-x.x.x.jar com.alibaba.druid.filter.config.security.tool.Main</b>
|
||||
*
|
||||
* </pre>
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class Main {
|
||||
private static boolean isEnd = false;
|
||||
|
||||
private static HelpAction help = new HelpAction();
|
||||
|
||||
static {
|
||||
int i = 1;
|
||||
help.addAction(Integer.toString(i++), new RsaAction());
|
||||
help.addAction("h", help);
|
||||
help.addAction("q", new QuitAction());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
header();
|
||||
help.execute();
|
||||
|
||||
while(!isEnd) {
|
||||
String input = System.console().readLine("请输入选项: ");
|
||||
input = input.toLowerCase();
|
||||
Action action = help.getAction(input);
|
||||
if (action == null) {
|
||||
System.err.println(input + " 不是一个合法的选项.[如需要帮助请输入 h]");
|
||||
continue;
|
||||
} else {
|
||||
action.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void header() {
|
||||
System.out.println("**************************************");
|
||||
System.out.println("* *");
|
||||
System.out.println("* Druid 加密工具 *");
|
||||
System.out.println("* *");
|
||||
System.out.println("**************************************");
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.alibaba.druid.filter.config.security.tool;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class QuitAction implements Action {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "QUIT";
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
foot();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void foot() {
|
||||
System.out.println("**************************************");
|
||||
System.out.println("* *");
|
||||
System.out.println("* 再 见 了 *");
|
||||
System.out.println("* *");
|
||||
System.out.println("**************************************");
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,6 @@ import javax.sql.DataSource;
|
||||
import com.alibaba.druid.filter.Filter;
|
||||
import com.alibaba.druid.filter.FilterChainImpl;
|
||||
import com.alibaba.druid.filter.FilterManager;
|
||||
import com.alibaba.druid.filter.config.ConfigFilter;
|
||||
import com.alibaba.druid.pool.DruidDataSource.ActiveConnectionTraceInfo;
|
||||
import com.alibaba.druid.pool.vendor.NullExceptionSorter;
|
||||
import com.alibaba.druid.proxy.jdbc.DataSourceProxy;
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ConfigFilterTest extends ConfigFileGenerator {
|
||||
dataSource.setUsername("test");
|
||||
dataSource.setPassword(encryptedString);
|
||||
dataSource.setFilters("config");
|
||||
dataSource.setConnectionProperties("config.decrypt=RSA");
|
||||
dataSource.setConnectionProperties("config.decrypt=true");
|
||||
|
||||
try {
|
||||
dataSource.init();
|
||||
@@ -84,32 +84,11 @@ public class ConfigFilterTest extends ConfigFileGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitInvalidDecrypt() throws SQLException {
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
dataSource.setDriver(MockDriver.instance);
|
||||
dataSource.setUrl("");
|
||||
dataSource.setUsername("test");
|
||||
dataSource.setPassword(encryptedString);
|
||||
dataSource.setFilters("config");
|
||||
dataSource.setConnectionProperties("config.decrypt=ABCDEF");
|
||||
|
||||
Exception error = null;
|
||||
try {
|
||||
dataSource.init();
|
||||
} catch (IllegalArgumentException e) {
|
||||
error = e;
|
||||
} finally {
|
||||
JdbcUtils.close(dataSource);
|
||||
}
|
||||
Assert.assertNotNull(error);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitRemoteConfigAndDecrypt() throws SQLException {
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
dataSource.setFilters("config");
|
||||
dataSource.setConnectionProperties("config.decrypt=RSA;config.file=" + "file://" + this.filePath);
|
||||
dataSource.setConnectionProperties("config.decrypt=true;config.file=" + "file://" + this.filePath);
|
||||
try {
|
||||
dataSource.init();
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.alibaba.druid.bvt.filter.config;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.alibaba.druid.filter.config.security.decrypter.DecryptException;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.DecrypterFactory;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.RsaDecrypter;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class DecrypterFactoryTest {
|
||||
|
||||
@Test
|
||||
public void testGetDecrypter() throws DecryptException {
|
||||
Assert.assertNotNull(DecrypterFactory.getDecrypter("RSA"));
|
||||
Assert.assertEquals(DecrypterFactory.getDecrypter("RSA").getClass(), RsaDecrypter.class);
|
||||
|
||||
Assert.assertNull(DecrypterFactory.getDecrypter("ajfdjksfklds;"));
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
package com.alibaba.druid.bvt.filter.config;
|
||||
|
||||
import com.alibaba.druid.filter.config.security.decrypter.DecryptException;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.RsaDecrypter;
|
||||
import com.alibaba.druid.filter.config.security.decrypter.SensitiveParameters;
|
||||
import com.alibaba.druid.util.Base64;
|
||||
import junit.framework.Assert;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class RsaDecrypterTest {
|
||||
String publicKeyContent = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2YdTlkEw7JfRNItCosRf4QO8vOL54ZEdj0LZm" +
|
||||
"tKhNFnNRTtHrLDFT44BPYqFSLVv3TOhLxJcEs31kyQhXEC5b9ozpZBvYrJDSt8QQMoYDAMLSojs+" +
|
||||
"K4vTJavgbRKKads0di+DuoMmJ5g5dcbDNd1Kb4kgWhrZtUwhfSjQklaiIwIDAQAB";
|
||||
|
||||
String encryptedString = "Zaa9qpyB9snnBUz7UBvcaHcNfWMKEWvhnx0dbWmwxBOJ9vkeZNXjV9MEJezSzL+6yQh7aO29vD67" +
|
||||
"qedtD9ublVwwf+jTPuO1NjzAKy0+yWVQ1KdR2KaQuvCxFWiM1n6nbpkUGB6OVpoQgFnFzdKlyC9D" +
|
||||
"KU3Q6evGa1hlZ8jnHcA=";
|
||||
|
||||
String keyFilePath;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
File tmp = File.createTempFile("druid_public_key", Long.toString(System.currentTimeMillis()));
|
||||
byte[] keyContent = Base64.base64ToByteArray(this.publicKeyContent);
|
||||
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(tmp);
|
||||
out.write(keyContent);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
this.keyFilePath = tmp.getAbsolutePath();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
File tmp = new File(this.keyFilePath);
|
||||
if (tmp.exists()) {
|
||||
tmp.delete();
|
||||
}
|
||||
|
||||
this.keyFilePath = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPublicKeyByString() {
|
||||
RsaDecrypter rsaDecrypter = new RsaDecrypter();
|
||||
PublicKey key = rsaDecrypter.getPublicKeyByString(this.publicKeyContent);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
|
||||
key = rsaDecrypter.getPublicKeyByString(null);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
Assert.assertEquals(RsaDecrypter.DEFAULT_PUBLIC_KEY_STRING, Base64.byteArrayToBase64(key.getEncoded()));
|
||||
|
||||
try {
|
||||
key = rsaDecrypter.getPublicKeyByString("abcdef");
|
||||
Assert.assertTrue("It is here", false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPublicKeyByPublicKeyFile() {
|
||||
RsaDecrypter rsaDecrypter = new RsaDecrypter();
|
||||
PublicKey key = rsaDecrypter.getPublicKeyByPublicKeyFile(this.keyFilePath);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
|
||||
key = rsaDecrypter.getPublicKeyByPublicKeyFile(null);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
Assert.assertEquals(RsaDecrypter.DEFAULT_PUBLIC_KEY_STRING, Base64.byteArrayToBase64(key.getEncoded()));
|
||||
|
||||
try {
|
||||
key = rsaDecrypter.getPublicKeyByPublicKeyFile("abcdef");
|
||||
Assert.assertTrue("It is here", false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPublicKeyByX509File() {
|
||||
//No test
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPublicKey() {
|
||||
RsaDecrypter rsaDecrypter = new RsaDecrypter();
|
||||
PublicKey key = rsaDecrypter.getPublicKey(null);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
Assert.assertEquals(RsaDecrypter.DEFAULT_PUBLIC_KEY_STRING, Base64.byteArrayToBase64(key.getEncoded()));
|
||||
|
||||
Properties info = new Properties();
|
||||
info.put(RsaDecrypter.KEY, this.publicKeyContent);
|
||||
key = rsaDecrypter.getPublicKey(info);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
Assert.assertEquals(this.publicKeyContent, Base64.byteArrayToBase64(key.getEncoded()));
|
||||
|
||||
info = new Properties();
|
||||
info.put(RsaDecrypter.KEY_FILE, this.keyFilePath);
|
||||
key = rsaDecrypter.getPublicKey(info);
|
||||
Assert.assertNotNull("It is null", key);
|
||||
Assert.assertEquals(this.publicKeyContent, Base64.byteArrayToBase64(key.getEncoded()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecrypt() throws DecryptException {
|
||||
RsaDecrypter decrypter = new RsaDecrypter();
|
||||
Properties info = new Properties();
|
||||
info.put(RsaDecrypter.KEY_FILE, this.keyFilePath);
|
||||
SensitiveParameters parameters = decrypter.decrypt(new SensitiveParameters("", "", encryptedString), info);
|
||||
|
||||
Assert.assertEquals("It is not same.", "xiaoyu", parameters.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecryptWithEmptyKey() throws DecryptException {
|
||||
RsaDecrypter decrypter = new RsaDecrypter();
|
||||
SensitiveParameters parameters = decrypter.decrypt(new SensitiveParameters("", "", "OJfUm6WCHi7EuXqE6aEc+Po2xFrAGBeSNy8O2jWhV2FTG8/5kbRRr2rjNKhptlevm/03Y0048P7h88gdUOXAYg=="), (Properties) null);
|
||||
|
||||
Assert.assertEquals("It is not same.", "xiaoyu", parameters.getPassword());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.alibaba.druid.filter.config;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSourceFactory;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -32,11 +34,7 @@ public class ConfigFileGenerator {
|
||||
} catch (IOException e) {
|
||||
Assert.assertNull("Failed to init resource.", e);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch(Exception e){}
|
||||
}
|
||||
JdbcUtils.close(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user