Spring支持配置文件加解密解決方案/數據庫配置加密讀取解決方案

最近的項目有這樣一個需求:spring配置文件中的數據源配置需要加密,也就是讀取的jdbc.properties文件中的url、username、password等參數需要進行DES加密,然後在spring把參數賦值給數據源之前解密。

先來看看Spring的一段配置:


<context:property-placeholder file-encoding="UTF-8" location="classpath:/config.properties,classpath:/jdbc.properties" ignore-resource-not-found="true" />


這裏的配置就是spring在項目啓動時將配置文件中的屬性讀取到了spring容器中。此處這段配置其實就是創建PropertySourcesPlaceholderConfigurer這個類來進行的管理。各位按ctrl點擊標籤可以看到spring-context.xsd中的詳細信息。

PropertySourcesPlaceholderConfigurer類經過一系列繼承關係,實質是一個容器後管理器。debug走裏面的一段代碼如下:
這裏寫圖片描述
進入這個mergeProperties()方法裏面看:
這裏寫圖片描述
可以看到localOverride這個屬性是用來控制是否覆蓋Spring讀取的屬性配置。並且下面緊跟着判斷this.localProperties!=null,如果localProperties不爲null的話,會讀取這些配置信息到spring容易中並且覆蓋spring中已存在的屬性。
知道這些後,我們在來看看如下配置:

<!-- 這裏的local-override="true" 就是覆蓋spring容器中已存在的屬性,properties-ref="dataSourceProperties" 是指定自己的properties -->
<context:property-placeholder local-override="true" properties-ref="dataSourceProperties" file-encoding="UTF-8" location="classpath:/config.properties,classpath:/jdbc.properties" ignore-resource-not-found="true" />
<!-- 這個類是我自定義的,用來解密jdbc.properties中的屬性之後然後存放到Properties類中 -->
<bean id="dataSourceProperties" class="com.sh.point.spring.propertiesHandle.DataSourceProperties">
		<constructor-arg value="point.read.jdbc.username,point.read.jdbc.password,point.read.jdbc.url,point.write.jdbc.username,point.write.jdbc.password,point.write.jdbc.url"/>
	</bean>

下面是我的DataSourceProperties類:

package com.sh.point.spring.propertiesHandle;

import com.sh.point.constant.Constant;
import com.sh.point.utils.DES;

import java.io.IOException;
import java.util.Properties;

/**
 * 數據源配置參數處理
 * <p/>
 * 配置信息事先被DES加密處理,需要在此解密然後綁定到數據源
 * Created by Alvin on 2016/7/31.
 */
public class DataSourceProperties extends Properties {

    /**
     * 構造方法
     * @param propertyNames 需要解密的屬性名稱
     */
    public DataSourceProperties(String[] propertyNames) {
        try {
            this.load(DataSourceProperties.class.getResourceAsStream("/jdbc.properties"));
            for (String propertyName : propertyNames) {
                decrypt(propertyName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解密
     */
    private void decrypt(String propertyName) {
        String value = DES.decrypt(this.getProperty(propertyName), Constant.ENCRYPT_KEY);
        this.setProperty(propertyName, value);
    }
    
}

然後我的數據源配置如下:

<bean id="pointRead" class="com.atomikos.jdbc.AtomikosDataSourceBean"
		  init-method="init" destroy-method="close">
		<description>mysql xa datasource</description>
		<property name="uniqueResourceName">
			<value>pointRead1</value>
		</property>
		<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
		<property name="xaProperties">
			<props>
				<prop key="user">${point.read.jdbc.username}</prop>
				<prop key="password">${point.read.jdbc.password}</prop>
				<prop key="URL">${point.read.jdbc.url}</prop>
			</props>
		</property>
		<!-- 連接池裏面連接的個數? -->
		<property name="poolSize" value="3"/>
	</bean>

jdbc.properties裏面的屬性加密過後如下:

point.read.jdbc.url=csRbLXGXGZ65TOILxkSPCOyJksX4F0kyPy/iKeGKC0g8F4eKZFmW7ynoYjceDsrfhTtF7TC/dM0YgXAYcd9DjB5OdIulTJvHkqD458IMRC0m7pmKQb26lLj3VF0jlh+gZegrg8Y/D7o=
point.read.jdbc.username=BbeUz7wzHcE=
point.read.jdbc.password=XcZSWnefvog=

point.write.jdbc.url=csRbLXGXGZ65TOILxkSPCOyJksX4F0kyPy/iKeGKC0g8F4eKZFmW7ynoYjceDsrfhTtF7TC/dM0YgXAYcd9DjB5OdIulTJvHkqD458IMRC0m7pmKQb26lLj3VF0jlh+gZegrg8Y/D7o=
point.write.jdbc.username=BbeUz7wzHcE=
point.write.jdbc.password=XcZSWnefvog=

這樣就實現了上面的需求。properties文件中的屬性加密,然後spring讀取的時候先由上面的自己寫的DataSourceProperties類來進行解密並且存儲替換,然後spring就會把解密過後的屬性存放在容器,並且根據spring配置文件中的EL表達式注入到數據源中。

搞定!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章