Spring对外部属性文件指定的某个属性进行加密、解密
2012-03-08 18:18
471 查看
在我们开发当中,经常会用到spring框架来读取属性文件的属性值,然后使用占位符引用属性文件的属性值来简化配置以及使配置具有更高的灵活性和通用性。
如下面的属性配置文件:db.properties
#数据库配置
db.driver=org.postgresql.Driver
db.url=jdbc\:postgresql\://10.166.176.127\:5432/test
db.username=ivsadmin
db.password=123456
db.name=ivs
applicationContext.xml文件
对于一些敏感的属性值,例如:密码属性。为了达到安全目的,我们一般会将密码进行加密。
可能希望用户看到db.properties是这样的:
#数据库配置
db.driver=org.postgresql.Driver
db.url=jdbc\:postgresql\://10.166.176.127\:5432/ivs
db.username=ivsadmin
db.password={SMC}sYNzVKgIhOprkdGhCyt81w==
db.name=ivs
这里可以看到密码属性值是加密过的,其它的属性值不变,这样就达到安全目的。这里采用的是java的3DES加密,在前面的文章中 3DES加密、解密工具类 已经有介绍了
下面开始分析下我们的需求:
在Spring中担负对外在化应用参数的配置的是PropertyPlaceholderConfigurer和PropertyOverrideConfigurer对象,PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor接口,它能够对<bean/>中的属性值进行外在化管理。
就像这样:
为简化PropertyPlaceholderConfigurer的使用,Spring提供了<context:property-placeholder/>元素,像applicationContext.xml文件中这样:<context:property-placeholder
location="classpath:db.properties" />
这里就很清楚了,我们只要继承PropertyPlaceholderConfigurer对象,重写PropertiesLoaderSupport接口的loadProperties方法,就可以对外部属性文件的属性值进行相关的操作了
明白了需求,下来开始我们的实现代码:
DecryptPropertyPlaceholderConfigurer.java
其中propertiesPersister变量用我们写的DefaultPropertiesPersister类来实现,DecryptPropertiesPersister.java对象
最后需要修改下applicationContext.xml文件,如下:
这样对属性的加密就完成了,Spring进行加载的完成后,属性就加密了
提示:如果在配置中有多个配置文件需要加载,并且这些属性文件不需要做任何处理,那就需要添加下面的配置:
如下面的属性配置文件:db.properties
#数据库配置
db.driver=org.postgresql.Driver
db.url=jdbc\:postgresql\://10.166.176.127\:5432/test
db.username=ivsadmin
db.password=123456
db.name=ivs
applicationContext.xml文件
<context:property-placeholder location="classpath:db.properties" /> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${db.driver}" /> <property name="jdbcUrl" value="${db.url}" /> <property name="user" value="${db.username}" /> <property name="password" value="${db.password}" /> <property name="checkoutTimeout" value="3000" /> </bean>
对于一些敏感的属性值,例如:密码属性。为了达到安全目的,我们一般会将密码进行加密。
可能希望用户看到db.properties是这样的:
#数据库配置
db.driver=org.postgresql.Driver
db.url=jdbc\:postgresql\://10.166.176.127\:5432/ivs
db.username=ivsadmin
db.password={SMC}sYNzVKgIhOprkdGhCyt81w==
db.name=ivs
这里可以看到密码属性值是加密过的,其它的属性值不变,这样就达到安全目的。这里采用的是java的3DES加密,在前面的文章中 3DES加密、解密工具类 已经有介绍了
下面开始分析下我们的需求:
在Spring中担负对外在化应用参数的配置的是PropertyPlaceholderConfigurer和PropertyOverrideConfigurer对象,PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor接口,它能够对<bean/>中的属性值进行外在化管理。
就像这样:
<bean id="propertyConfigurer1" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <value>WEB-INF/classes/db.properties</value> </property> </bean>
为简化PropertyPlaceholderConfigurer的使用,Spring提供了<context:property-placeholder/>元素,像applicationContext.xml文件中这样:<context:property-placeholder
location="classpath:db.properties" />
这里就很清楚了,我们只要继承PropertyPlaceholderConfigurer对象,重写PropertiesLoaderSupport接口的loadProperties方法,就可以对外部属性文件的属性值进行相关的操作了
明白了需求,下来开始我们的实现代码:
DecryptPropertyPlaceholderConfigurer.java
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Properties; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.core.io.Resource; import com.huawei.smc.commons.constants.CommonContants; /** * <一句话功能简述> * * @author hKF44803 * @version [版本号, 2011-12-6] * @see [相关类/方法] * @since [产品/模块版本] */ public class DecryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { private Resource[] locations; private DecryptPropertiesPersister propertiesPersister = new DecryptPropertiesPersister(); private String fileEncoding = "utf-8"; private boolean ignoreResourceNotFound = false; /** * {@inheritDoc} */ @Override public void setLocations(Resource[] locations) { this.locations = locations; } /** * {@inheritDoc} */ @Override public void setFileEncoding(String encoding) { this.fileEncoding = encoding; } /** * {@inheritDoc} */ @Override public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) { this.ignoreResourceNotFound = ignoreResourceNotFound; } /** * {@inheritDoc} */ @Override public void loadProperties(Properties props) throws IOException { // 属性文件是否为空 if (this.locations != null) { // 循环读取属性文件 for (int i = 0; i < this.locations.length; i++) { Resource location = this.locations[i]; InputStream is = null; FileOutputStream fos = null; try { is = location.getInputStream(); // 检查文件是否是XML文件 if (location.getFilename().endsWith(XML_FILE_EXTENSION)) { this.propertiesPersister.loadFromXml(props, is); } // 属性文件 else { this.propertiesPersister.doLoad(props, new InputStreamReader(is, this.fileEncoding)); String content = this.propertiesPersister.getEncryptContent(); // 查找是否存在加密标识 if (StringUtils.contains(content, CommonContants.DECRYPT_FLAG)) { try { File file = location.getFile(); fos = new FileOutputStream(file); fos.write(this.propertiesPersister.getEncryptContent().getBytes()); fos.flush(); } finally { if (null != fos) { fos.close(); } } } } } catch (IOException ex) { if (this.ignoreResourceNotFound) { if (logger.isWarnEnabled()) { logger.warn("Could not load properties from " + location + ": " + ex.getMessage()); } } else { throw ex; } } finally { if (is != null) { is.close(); } } } } } }
其中propertiesPersister变量用我们写的DefaultPropertiesPersister类来实现,DecryptPropertiesPersister.java对象
import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.util.Properties; import org.springframework.util.DefaultPropertiesPersister; import org.springframework.util.StringUtils; import com.huawei.smc.commons.constants.CommonContants; import com.huawei.smc.commons.constants.NumberConstants; import com.huawei.smc.commons.util.ThreeDesUtil; /** * 重载DefaultPropertiesPersister类 * * @author hKF44803 * @version [版本号, 2011-12-6] * @see [相关类/方法] * @since [产品/模块版本] */ public class DecryptPropertiesPersister extends DefaultPropertiesPersister { // 加密后的字符串 private String encryptContent; public String getEncryptContent() { return encryptContent; } /** * {@inheritDoc} */ @Override protected void doLoad(Properties props, Reader reader) throws IOException { BufferedReader in = new BufferedReader(reader); // 最后写入的内容 StringBuilder sbContent = new StringBuilder(); // 循环读取文件 while (true) { // 读取每一行 String line = in.readLine(); // 非空检查 if (line == null) { break; } // 去掉空格 line = StringUtils.trimLeadingWhitespace(line); // 读取行为空,跳出循环 if (line.length() == 0) { // 长度为0,换行 sbContent.append("\n"); continue; } // 每行的第一个字符 char firstChar = line.charAt(0); // 第一个字符不是#和! if (firstChar != '#' && firstChar != '!') { while (endsWithContinuationMarker(line)) { String nextLine = in.readLine(); line = line.substring(0, line.length() - 1); // 非空检查 if (nextLine != null) { line += StringUtils.trimLeadingWhitespace(nextLine); } } // 查找等号所有位置的索引 int separatorIndex = line.indexOf("="); // 没有等号 if (separatorIndex == -1) { separatorIndex = line.indexOf(":"); } // 取KEY String key = (separatorIndex != -1) ? line.substring(0, separatorIndex) : line; // 取KEY的值 String value = (separatorIndex != -1) ? line.substring(separatorIndex + 1) : ""; // 去掉空格 key = StringUtils.trimTrailingWhitespace(key); value = StringUtils.trimLeadingWhitespace(value); // 将所有的属性放到持久的属性集* props.put(unescape(key), unescape(value)); // DB属性文件 if (CommonContants.DB_PASSWORD_PROPS.equals(key)) { // 实例加密工具类 ThreeDesUtil desUtil = new ThreeDesUtil(); // DB密码解密 if (value.startsWith(CommonContants.DECRYPT_FLAG)) { // 去掉标识 value = value.substring(NumberConstants.INT_5); // 对加密的属性进行3DES解密 value = desUtil.decrypt(value); // 解密的值放到props中 props.put(unescape(key), unescape(value)); } // DB密码加密 else { // 加密指定的值 String strEncrypt = desUtil.encrypt(value); // 加密后的值添加一个标识,区分解密、加密 value = CommonContants.DECRYPT_FLAG + strEncrypt; // 加密后的行 line = key + CommonContants.PROPERTIES_SEPERATE + value; sbContent.append(line + "\n"); } } // 追加其它的属性 else { sbContent.append(line + "\n"); } } else { // 追加读取的注释内容 sbContent.append(line + "\n"); } } encryptContent = sbContent.toString(); } }
最后需要修改下applicationContext.xml文件,如下:
<bean id="propertyConfigurer1" class="com.huawei.smc.commons.DecryptPropertyPlaceholderConfigurer"> <property name="locations"> <value>WEB-INF/classes/db.properties</value> </property> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${db.driver}" /> <property name="jdbcUrl" value="${db.url}" /> <property name="user" value="${db.username}" /> <property name="password" value="${db.password}" /> <property name="checkoutTimeout" value="3000" /> </bean>
这样对属性的加密就完成了,Spring进行加载的完成后,属性就加密了
提示:如果在配置中有多个配置文件需要加载,并且这些属性文件不需要做任何处理,那就需要添加下面的配置:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="order" value="1" /> <property name="ignoreUnresolvablePlaceholders" value="true" /> <property name="locations"> <value>WEB-INF/classes/smc.properties</value> </property>
相关文章推荐
- Spring对外部属性文件指定的某个属性进行加密、解密
- spring-使用外部属性文件及加密解密文件属性
- java spring中对properties属性文件加密及其解密
- Spring对属性文件加密解密应用详解
- java spring中对properties属性文件加密及其解密
- Spring 对属性文件的加密与解密
- Spring对属性文件加密解密应用
- java spring中对properties属性文件加密及其解密
- Spring中对properties属性文件加密及其解密
- 在Spring中如何使用加密外部属性文件
- java spring中对properties属性文件加密及其解密
- 读取本地json文件,转出为指定格式json 使用Base64进行string的加密和解密
- java spring中对properties属性文件加密及其解密
- java spring中对properties属性文件加密及其解密
- Spring 管理下的web项目,对Properties文件重要参数的加密解密处理
- 扩展Spring--外部属性文件安全(二)
- Spring中扩展 PropertyPlaceholderConfigurer处理加密属性文件
- 使用对称加密aes对文件进行zip加密解密
- (五)spring配置文件--使用外部属性文件
- java中使用异或的方式对文件进行加密解密