javaWeb项目中往往我们会把jdbc/redis等的属性配置放在properties文件中,但是又不想让非开发人员看到某些重要配置信息,所以需要对这样类似与用户名、密码等的字段进行加密,但是Spring管理项目启动时候只去读取,所以必须继承PropertyPlaceholderConfigurer 类来实现读取前的解密过程
加密类
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
public class DesEncryptUtil
{
public static void main(String[] args) throws Exception
{
/** 生成KEY */
Key key = getKey("../key");
/** 加密 */
byte[] result = doEncrypt(key, "");
String buf = "";
for (int i = 0; i < result.length; i++)
{
buf += result[i] + ",";
}
System.out.println(buf);
/** 解密 */
}
@SuppressWarnings("restriction")
public static void createKey(String keyFilePath) throws Exception
{
Security.insertProviderAt(new com.sun.crypto.provider.SunJCE(), 1);
KeyGenerator generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom());
Key key = generator.generateKey();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(keyFilePath));
oos.writeObject(key);
oos.close();
}
@SuppressWarnings("resource")
public static Key getKey(String keyFilePath)
{
try
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(keyFilePath));
return (Key) ois.readObject();
}
catch (Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static byte[] doEncrypt(Key key, String str)
{
try
{
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] raw = cipher.doFinal(str.getBytes());
return raw;
}
catch (Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static String doDecrypt(Key key, String buf)
{
try
{
String[] strArray = buf.split(",");
byte[] resultStr = new byte[strArray.length];
for (int i = 0; i < strArray.length; i++)
{
resultStr[i] = new Byte(strArray[i]) ;
}
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] raw = cipher.doFinal(resultStr);
return new String(raw);
}
catch (Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
之所以该类加密的不是文件而是字符串,是有部分原因的:
1- 一般数据库等重要配置信息不是单独放在一个properties文件中的,其下面还是会有其他配置参数的,但是那些参数我们并不想去加密,甚至回经常去修改。
2- 如果加密的是整个properties文件,当修改其他参数麻烦,系统启动错误或者其他配置的bug,也不好去查找。
如果需要去对整个文件加密,可以去看一下 http://blog.csdn.net/yaerfeng/article/details/26561791 中的加密方法。
PropertiesConstant常量类
public class PropertiesConstant
{
public static final String REDIS_HOST = "redis.host";
public static final String REDIS_PORT = "redis.port";
public static final String REDIS_PASS = "redis.pass";
public static final String JDBC_URL = "jdbc_url";
public static final String JDBC_USERNAME = "jdbc_username";
public static final String JDBC_PASSWORD = "jdbc_password";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
DecryptPropertyPlaceholderConfigurer 类
import java.security.Key
import java.util.Properties
import org.springframework.beans.BeansException
import org.springframework.beans.factory.BeanInitializationException
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
import com.rrcp.mgmt.util.DesEncryptUtil
import com.rrcp.mgmt.util.PropertiesConstant
public class DecryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer
{
private final String rootPath = getClass().getResource("/").getFile().toString()
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException
{
Key key = DesEncryptUtil.getKey(rootPath + "../key")
try
{
String redis_host = props.getProperty(PropertiesConstant.REDIS_HOST)
if(redis_host != null)
{
props.setProperty(PropertiesConstant.REDIS_HOST, DesEncryptUtil.doDecrypt(key, redis_host))
}
String redis_port = props.getProperty(PropertiesConstant.REDIS_PORT)
if(redis_port != null)
{
props.setProperty(PropertiesConstant.REDIS_PORT, DesEncryptUtil.doDecrypt(key, redis_port))
}
String redis_pass = props.getProperty(PropertiesConstant.REDIS_PASS)
if(redis_pass != null)
{
props.setProperty(PropertiesConstant.REDIS_PASS, DesEncryptUtil.doDecrypt(key, redis_pass))
}
String jdbc_url = props.getProperty(PropertiesConstant.JDBC_URL)
if(jdbc_url != null)
{
props.setProperty(PropertiesConstant.JDBC_URL, DesEncryptUtil.doDecrypt(key, jdbc_url))
}
String jdbc_username = props.getProperty(PropertiesConstant.JDBC_USERNAME)
if(jdbc_username != null)
{
props.setProperty(PropertiesConstant.JDBC_USERNAME, DesEncryptUtil.doDecrypt(key, jdbc_username))
}
String jdbc_password = props.getProperty(PropertiesConstant.JDBC_PASSWORD)
if(jdbc_password != null)
{
props.setProperty(PropertiesConstant.JDBC_PASSWORD, DesEncryptUtil.doDecrypt(key, jdbc_password))
}
super.processProperties(beanFactory, props)
}
catch (Exception e)
{
e.printStackTrace()
throw new BeanInitializationException(e.getMessage())
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
SpringConfig.xml中的配置(关键)
注意:如果使用自定义的类来加载properties文件,需要配置<bean id="propertyConfigurer"....></bean>
,并且红色框1处不能存在,因为原本是通过上面的配置加载文件的,现在添加了下面的方式两种方式就不能并存了(建议将红框中的配置文件全放在下面的value中),否则会启动失败