对于安全考虑需要对.properties中部分敏感数据进行加密(如:密码不能明文显示)。项目中使用了Spring3框架统一加载属性文件,所以最好可以干扰这个加载过程来实现对.properties文件中的部分属性进行解密。这时候PropertyPlaceholderConfigurer就可大显身手了。
在上一篇的前提下,继承更新:
java bean:
package org.demo.model;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
public class EmpModel {
private String name;
private int age;
private char gender;
private String password;
@Autowired
private PhoneModel phone;
@Resource
private CarModel car;
//相应的get\set\toString
}
emp.properties:
emp.name=wang
emp.age=12
emp.gender=f
# AGgKdx/Qic8= 是将12345加密后的
emp.password=AGgKdx/Qic8=
applicationContext.xml
<bean id="empModel" class="org.demo.model.EmpModel">
<property name="name"><value>${emp.name}</value></property>
<property name="age"><value>${emp.age}</value></property>
<property name="gender"><value>${emp.gender}</value></property>
<property name="password"><value>${emp.password}</value></property>
</bean>
**如果这样取的话 password会是
加密的字符,这样是不对的
现在继承PropertyPlaceholderConfigurer干预加载.properties文件。
package org.demo.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class CustomPropertyConfigurer extends PropertyPlaceholderConfigurer {
private static final Logger logger = Logger.getLogger(CustomPropertyConfigurer.class);
private static Map<String, String> ctxPropertiesMap = new HashMap<String, String>();
private static final String KEY = "12345678";
/**
* 对指定的属性进行解密处理,并将解密后的信息又放回去。
* @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#processProperties(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.Properties)
*/
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
logger.info("==============开始加载.properties配置文件=============");
//取得已经加密emp.password属性的value, empPassword为AGgKdx/Qic8=
String empPassword = props.getProperty("emp.password");
if (empPassword != null) {
//解密并,重新设置该属性的value
props.setProperty("emp.password",DesUtil.decrypt(empPassword, KEY));
}
//如果还有其它属性就照搬上面的样式。
//交由父类继续处理(一定要写在最后面)
// super.processProperties(beanFactory, props);
//扩展
setCtxPropertiesMap(beanFactory,props);
logger.info("==============加载.properties配置文件完毕=============");
}
/**
*
* 解密后将所有属性注入ctxPropertiesMap。<p>
* 扩展:如果不是spring上下文中注入,而是从某个类中取.properties文件中的属性。
*
* @author wangxinyu
*
* @param props
*/
private void setCtxPropertiesMap(ConfigurableListableBeanFactory beanFactory,Properties props){
for (Object key : props.keySet()) {
//交由父类继续处理
super.processProperties(beanFactory, props);
String keyStr = key.toString();
String value = props.getProperty(keyStr);
ctxPropertiesMap.put(keyStr, value);
}
}
// 根据key取value
public static String getProperty(String name) {
return ctxPropertiesMap.get(name);
}
}
好了,现在测试
import org.apache.log4j.Logger;
import org.demo.model.EmpModel;
import org.demo.util.CustomPropertyConfigurer;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class GetBeanTest {
private static final Logger logger = Logger.getLogger(GetBeanTest.class);
ApplicationContext ac;
@Before
public void init() {
ac = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void getEmpModelBean(){
EmpModel emp = ac.getBean("empModel",EmpModel.class);
logger.info("emp.name:"+CustomPropertyConfigurer.getProperty("emp.name"));
logger.info(emp);
}
}
**成功!