spring datasource 密码加密后运行时解密的解决办法

在做项目的时候,有些客户要求不能直接明文暴露密码,因此需要对密码进行加密处理。当然很多项目也没有这样的要求,原因也很简单,要查看密码需要登录服务器,如果能登录服务器的人,权限肯定不一般。当然我今天要记录的就是需要加密的时候怎么处理。
一般我们配置spring datasource 可能会类似如下
程序代码 程序代码

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8" />
        <property name="username" value="root" />
        <property name="password" value="password" />
    </bean>        

还有另外一种方式,就是读取properties 方式,这种更常见了.比如
程序代码 程序代码

<context:property-placeholder
        location="classpath:/config/database.properties" />
        
    <bean id="data_source" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"
        p:maxActive="10" p:maxIdle="10">
    </bean>

这种情况下,数据库信息和密码保存在 database.properties 中。这种方式用的比较多,这里就用这种方式说明, 我们变更配置为如下:

程序代码 程序代码

<bean id= "configReader" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">    
        <property name = "1ocations">
           <list>
               <!-- 里面保存了加密的信息 -->
               <value>file:D:/database.properties</value>
           </list>
        </property>
        <property name="propertiesPersister">
            <bean class="com.yihaomen.propertiesextend.MyPropertiesPersist" />
        </property>
        <property name ="ignoreResourceNotFound" value="true"/>
    </bean>


你会看到有一个 com.yihaomen.propertiesextend.MyPropertiesPersist 类,这就是我们需要扩展的类了。扩展为如下:

程序代码 程序代码


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import org.springframework.util.DefaultPropertiesPersister;

public class MyPropertiesPersist extends DefaultPropertiesPersister {
    
    public void load(Properties props, InputStream is) throws IOException{
    
    Properties properties = new Properties();
    properties.load(is);
    
    if ( (properties.get("password") != null) ){
        /*这里通过解密算法,得到你的真实密码,然后写入到properties中*/
//        String password = getRealPassword( decrypter , properties.getProperty("password") );    
//        properties.setProperty("password" , password);     
    }    
    OutputStream outputStream = null;
    try {
        outputStream = new ByteArrayOutputStream();
        properties.store(outputStream, "");
        is = outStream2InputStream(outputStream);
        super.load(props, is);
    }catch(IOException e) {
        throw e;
    }finally {
        outputStream.close();
    }
    }
    
    
    private InputStream outStream2InputStream(OutputStream out){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bos = (ByteArrayOutputStream) out ;
        ByteArrayInputStream swapStream = new ByteArrayInputStream(bos.toByteArray());
        return swapStream;
    }
}


再次运行程序,你会发现 密码已经被解密了。datasource 被正确的密码注入,程序运行正常. 当然这只是其中一种方法用来扩展解密处理properties的情况,其实还可以采用如下方法:
1. 比较暴力的方法,直接修改spring 源代码,只修改处理properties  这一块.
2. 也是比较暴力的方法, 如果用了c3p0 的数据源,也可以修改源代码。
3. 比较推荐的方法, 扩展 spring 的 PreferencesPlaceholderConfigurer 这个类进行处理,我觉得比较耗
4. 采用上面介绍的方法,同时也是我在项目中用到的方法.

备注:如果想参考加密解密的,可以参考这篇文章 http://www.yihaomen.com/article/java/247.htm


除非申明,文章均为一号门原创,转载请注明本文地址,谢谢!
[本日志由 轻舞肥羊 于 2013-11-13 08:25 PM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: spring java
相关日志:
评论: 1 | 引用: 0 | 查看次数: -
回复回复dazi[2014-10-13 12:40 AM | del]
咨询下 我QQ  160497231
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.