项目有个需求,要对项目中的配置文件中的密码进行加密,那相对应就会产生另一个需求,解密。
加解密不是什么难事,不同的数据库连接池有不同的加解密方式。针对c3p0连接,我采用的解密策略是:在注入bean属性(密码)的时候进行解密。(这里可以了解一下创建bean的几种方式以及如何注入bean属性)
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="properties">
<bean class="com.asiainfo.lcims.ISMS.util.C3p0PasswordHandle" factory-method="getProperties">
<constructor-arg type="java.lang.String">
<value>${center.jdbc.password}</value>
</constructor-arg>
</bean>
</property>
<property name="user" value="${center.jdbc.user}"></property>
<property name="driverClass" value="${center.jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${center.jdbc.jdbcUrl}&rewriteBatchedStatements=true&autoReconnect=true"></property>
......
</bean>
public class C3p0PasswordHandle {
......
public static Properties getProperties(String password) throws Exception {
Properties properties = new Properties();
try {
//解密密码
properties.setProperty(PROP_PASSWORD, decrypt(password));
} catch (Exception e) {
logger.error("DatasourcePropertiesFactory getProperties is error!", e);
}
return properties;
}
......
}
一些次要的内容先省略。
用静态方法创建bean对象,再通过构造器方式注入bean属性。
这里有一个坑困扰我很久:
就是我这个password解密的部分一定要放在最上方,如果放在中间(比如放在user或者driverClass属性下面),就会导致password上面的属性全部为空。
就比如当时我把password放在了user下面,就会出现user为空的情况:
然后这个问题出现的最终原因在哪里呢?深入源码+打断点刨根问底了一下:
先看这张截图:
当我们先注入user属性的时候,会调用setUser()方法,这时候,dmds对象中的properties属性会新增 user= fpss 这个值。没什么问题对吧,但是当我们再进行password属性注入的时候,就会调用上面的setProperties()方法了,这个时候传进来的是properties对象,注意一下参数中只有password了!!!
为什么呢?上面的代码块中其实已经说明了情况 T.T
new了一个新的properties对象,然后只塞了一个password…然后调用这个setProperties()方法,就重新给我们的dmds重新覆盖掉了,之前的user当然也存在了。。。
所以要么就把password放在最上面,要么再new Properties对象的时候,把前面的属性也都拿进来。
其实说完会发现也就这么回事,但是找原因的时候真的是非常的艹蛋,究其原因还是对于源码的掌握程度不够深刻。