现在的jdbc.properties配置如下:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_aplus?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=admin
第一个想法就是必须先写一个工具类,能把admin生成密文并且解密,还想到了DES加密算法。
/**
* 密码工具类
* Created by Li.fang on 2014/11/13.
*/
public class CipherUtils {
private static Logger logger = LoggerFactory.getLogger(CipherUtils.class);
//指定DES加密解密所用密钥
private static Key key;
private static String STR_SALT = "APLUS OFFICE SYSTEM";
private static final String GENERATOR_DES = "DES";
private static final String ENCODING_UTF8 = "UTF-8";
private static final int CIPHER_COUNT = 5;
static {
try {
KeyGenerator generator = KeyGenerator.getInstance(GENERATOR_DES);
generator.init(new SecureRandom(STR_SALT.getBytes()));
key = generator.generateKey();
generator = null;
}catch (NoSuchAlgorithmException e){
logger.warn("Cryptographic failure");
throw new RuntimeException(e);
}
}
/**
* 对字符串进行DES加密,返回BASE64编码的加密字符串
* @param str 需要加密的字符串
* @return 加密后的字符串
*/
public static String getEncryptBase64String(String str){
// BASE64Encoder base64Encoder = new BASE64Encoder();
try{
byte[] strBytes = str.getBytes(ENCODING_UTF8);
Cipher cipher= Cipher.getInstance(GENERATOR_DES);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptStrBytes = cipher.doFinal(strBytes);
return Base64.encodeBase64String(encryptStrBytes);
}catch (Exception e){
logger.warn("Cryptographic failure");
throw new RuntimeException(e);
}
}
/**
* 对BASE64编码的加密字符串进行解密,返回解密后的字符串
* @param str BASE64加密字符串
* @return 解密后的字符串
*/
public static String getDecryptString(String str){
// BASE64Decoder base64Decoder = new BASE64Decoder();
try{
byte[] strBytes = Base64.decodeBase64(str);
Cipher cipher= Cipher.getInstance(GENERATOR_DES);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptStrBytes = cipher.doFinal(strBytes);
return new String(decryptStrBytes, ENCODING_UTF8);
}catch (Exception e){
logger.warn("Decryption failure");
throw new RuntimeException(e);
}
}
}
网上一查,加密解密工具类搞定。
写了一个测试方法测试一下:
/**
* 测试加密
* @param args
*/
public static void main(String[] args){
//DES加密
String[] decryptStr = {"root","admin","jdbc:mysql://127.0.0.1/db_office?useUnicode=true&characterEncoding=utf-8"};
String[] encryptStr = new String[3];
for(int i = 0; i < decryptStr.length; i++){
encryptStr[i] = getEncryptBase64String(decryptStr[i]);
logger.info("{} : {}",decryptStr[i],getEncryptBase64String(decryptStr[i]));
}
for(int i = 0; i < encryptStr.length; i++){
logger.info("{} : {}",encryptStr[i],getDecryptString(encryptStr[i]));
}
}
把用户名,密码,数据连接地址都加密一下吧,要安全。。。。。
输入之后,把jdbc.properties替换:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=hmRjwCF4I0PtIuz1nXPPt52rPGY6XKU59SFJ5FYZFTSC6v6Ll70A4uM4F2Fyt3W4bfyzFukkv9eHneXYMpnk6nxVEdWEUCbJuzr+5AGega4=
jdbc.username=5MNmOVEG2r8=
jdbc.password=vApi3SXg+rs=
这样就已经加密成功,但不要高兴太早了,这只是第一步加密。。。。项目启动的时候,还得对其进行解密
<context:property-placeholder location="classpath:jdbc.properties"/>
以前都是这样直接引入jdbc.properties文件,现在可能不行了。 网上一查,发现已经引入配置文件,是通过org.springframework.beans.factory.config.PlaceholderConfigurerSupport进行解析的,那我就继承于他,自己写一个对值得属性名称进行解密。
package com.aplus.method;
import com.aplus.utils.CipherUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
/**
* 继承PropertyPlaceholderConfigurer,配置支持密文属性的属性文件
* Created by li.fang on 2014/11/13.
*/
public class EncryptPropertyConfigurer extends PropertyPlaceholderConfigurer{
private Logger logger = LoggerFactory.getLogger(EncryptPropertyConfigurer.class);
//需要解密的属性
private String[] encryptPropNames = {"jdbc.url","jdbc.username","jdbc.password"};
/**
* 对特定属性的属性值进行转换
* @param propertyName 属性名称
* @param propertyValue 属性值
* @return
*/
@Override
protected String convertProperty(String propertyName, String propertyValue) {
logger.info("The properties name is : {}, value is : ", propertyName, propertyValue);
if(isEncryptProp(propertyName)){
String decryptValue = CipherUtils.getDecryptString(propertyValue);
logger.info(decryptValue);
return decryptValue;
}else{
return propertyValue;
}
}
/**
* 判断属性是否需要解密
* @param propertyName
* @return
*/
private boolean isEncryptProp(String propertyName){
for(String encryptPropName : encryptPropNames){
if(StringUtils.equals(encryptPropName,propertyName)){
return true;
}
}
return false;
}
}
搞定。。。。方法对指定属性名称进行解密.
最后在引入jdbc.properties的时候,替换成:
<!-- 需要解密的文件 -->
<bean class="com.aplus.method.EncryptPropertyConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
<property name="fileEncoding" value="UTF-8"></property>
</bean>
测试OK.