创建SqlSessionFactory时对数据库配置中的加密用户名和密码进行解密操作示例

时间:2022-05-27 08:36:53

在实际的项目中,系统由运维人员去配置,生产数据库的用户名和密码对开发者是保密的。提供给开发者的数据库的用户名和密码是经过加密的,但是在创建SqlSessionFactory时需要提供明文密码。因此需要对加密的数据进行解密。

数据库配置文件

假设数据库配置文件为jdbc.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/forum
jdbc.username=root
jdbc.password=563739007


代码示例

以下便是创建SqlSessionFactory时对数据库配置中的加密用户名和密码进行解密操作示例。
代码已进行注释,不再进行讲解。

package forum.dao;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Enumeration;
import java.util.Properties;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

public class PropertiesRead {


    private static SqlSessionFactory sqlSessionFactory;


    @Test
    public  void init() {

        InputStream cfgStream = null;
        Reader      cfgReader = null;
        InputStream proStream = null;
        Reader      proReader = null;
        Properties  properties = new Properties();

        System.out.println("PropertiesRead statup");
        try {

            //读入Mybatis配置文件
            cfgStream = Resources.getResourceAsStream("res/mybatis/mybatis-config.xml");
            cfgReader = new InputStreamReader(cfgStream);
            //读入属性文件
            proStream = Resources.getResourceAsStream("config/jdbc.properties");
            proReader = new InputStreamReader(proStream);
            properties.load(proReader);
            //打印properties数据
            printProperties(properties);
            //解密操作 
            String newUserName =  sqlNameAndPasswordDecode("jdbc.username",properties.getProperty("jdbc.username"));
            String newUserPassword =  sqlNameAndPasswordDecode("jdbc.password",properties.getProperty("jdbc.password"));
            //将新的用户名和密码写入配置文件
            properties.setProperty("jdbc.username",newUserName);
            properties.setProperty("jdbc.password",newUserPassword);
            printProperties(properties);

            //创建sqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader,properties);

            cfgReader.close();
            proReader.close();

        }
        catch(IOException ex) {

            ex.printStackTrace();
        }
    }

    public SqlSession getSqlSession() {
        return PropertiesRead.sqlSessionFactory.openSession();
    }
    //打印属性信息
    public  void printProperties(Properties  properties){

        Enumeration<String> enu = (Enumeration<String>)properties.propertyNames();

        while(enu.hasMoreElements()) {
            String name = enu.nextElement();
            System.out.println( name + ":" + properties.getProperty(name));
        }
    }

    //对加密的用户名和密码进行解密
    //仅作为简单示例
    public String sqlNameAndPasswordDecode(String decodename,String decodevalue) {

        if(decodename.equals("jdbc.username") ) {
            return "newusername";
        }
        else if(decodename.equals("jdbc.password")) {
            return  "newpassword";
        }
        else {
            return null;
        }

    }

}


区别

与未进行解密操作的区别在于创建SqlSessionFactory时传入的参数不同
可参考未进行解密操作的写法

//未进行解密操作,也就是未对属性文件未进行更改`
//创建sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader);

//进行解密操作,也就是已对属性文件未进行更改`
//多传入参数properties,也就是新的配置
//创建sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader,properties);


优先级

Mybatis支持的3种配置方式可能同时出现,并且属性还是会重复配置。
这三种方式是存在优先级的,Mybatis会按照下面的顺序来进行加载。
1.在properties元素体内的属性首先被读取;
2.根据properties元素中的resource属性读取类路径下的属性文件,或者根据url属性指定的路径读取配置文件,并覆盖已读取的同名属性。
3.读取作为方法参数传递的属性,并覆盖已读取的同名属性。

因此通过方法参数传递的属性具有最高优先级,resource/url读取的属性次之,最低优先级为properties属性中指定的属性。
本示例中在创建SqlSessionFactory传入的properties属性便会覆盖掉在XML文件中属性。