MyBatis profile user password encrypted storage

properties profile

Generally, properties are used to save the contents of the configuration file, and then read them in the mybatis configuration file
Create a new db.properties file under the resource file
The contents are as follows

# Database profile
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://  /mybatis
username =  
password =   

Then, put the file in the source package
Configure mybatis-config.xml file

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- Read database configuration file -->
    <properties resource="db.properties"/>
    <!-- Define aliases -->
    <typeAliases>
        <typeAlias type="com.ming.Role" alias="role"/>
    </typeAliases>
    
    <!-- Custom data processing -->
    <typeHandlers>
        <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.ming.Sex"/>
    </typeHandlers>
    <!-- Define database information -->
    <environments default="development">
        <environment id="development">
            <!-- jdbc Affairs Management -->
            <transactionManager type="JDBC"/>
            <!-- Database link information -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <mapper resource="RoleMapper.xml"/>
    </mappers>
</configuration>

The directory structure is as follows

Database password encryption

The database passwords of the production environment are all encrypted passwords. When using, the encrypted passwords need to be decrypted into clear text
Create database password class first

package com.ming.Util;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Base64;

public class Decode {
    /**
     * Generate secret key
     * @param
     * @return
     */
    public static String generateDecode() throws UnsupportedEncodingException {
        KeyGenerator keyGen = null;//key generator 
        try {
            keyGen = KeyGenerator.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyGen.init(56);//Initialize key generator
        SecretKey secretKey = keyGen.generateKey();//Generating key
        byte[] key = secretKey.getEncoded();//Key byte array
        // base64 encoding
        String encodedKey = Base64.getEncoder().encodeToString(key);
        return encodedKey;
    }

    /**
     * Encrypt
     * @param string
     * @param key
     * @return
     */
    public static String encryptionDecode(String string, String key){
        //System.out.println(System.getenv("KEYWORDES"));
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//Recovery key
        Cipher cipher = null;//Cipher completes encryption or decryption work class
        try {
            cipher = Cipher.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);//Initialize Cipher, encryption mode
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        byte[] cipherByte = null;
        try {
            cipherByte = cipher.doFinal(Base64.getDecoder().decode(string));//Encrypted data
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(cipherByte);
    }

    public static String decryptDecode(String string, String key){
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//Recovery key
        Cipher cipher = null;//Cipher completes encryption or decryption work class
        try {
            cipher = Cipher.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.DECRYPT_MODE, secretKey);//Initialize Cipher, decrypt mode
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        byte[] cipherByte = new byte[0];//Decrypt data
        try {
            cipherByte = cipher.doFinal(Base64.getDecoder().decode(string));
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(cipherByte);
    }
}

This class has three methods: encrypt data, decrypt data, and generate key
Then edit the operating system environment variable
Achieve input

  ~ echo $KEYWORDES

Environment variables can be output
Then modify the SqlSessionFactoryUtil class again

package com.ming.Util;

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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

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

/**
 * @author ming
 * Build SqlSessionFactory
 * Because the database connection is precious and needs to be managed in a unified way, a single instance is used for management
 * The double lock used by the simple interest here
 * SqlSessionFactory Lock is required for thread unsafe types to ensure that only one thread can use the object at the same time
 */
public class SqlSessionFactoryUtil {

    /**
     * SqlSessionFactory object
     */
    private static SqlSessionFactory sqlSessionFactory = null;

    /**
     * Class thread lock
     */
    private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class;

    /**
     * Log management class
     */
    private static final Logger logger = LogManager.getLogger();
    /**
     * Single case
     */
    private SqlSessionFactoryUtil(){

    }

    /**
     * @return SqlSessionFactory
     * Initialize SqlSessionFactory object
     */
    public static SqlSessionFactory initSqlSessionFactory(){
       // Get input stream
       InputStream cfgStream = null;
       // Reading flow
       Reader cfgReader = null;
       InputStream proStream = null;
       Reader proReader = null;
       // Persistent property set
       Properties properties = null;
       try{
           // Profile flow
           cfgStream = Resources.getResourceAsStream("mybatis-config.xml");
           // Get reading stream
           cfgReader = new InputStreamReader(cfgStream);
           // Read in property file
           proStream = Resources.getResourceAsStream("db.properties");
           proReader = new InputStreamReader(proStream);
           // Persistent property set
           properties = new Properties();
           // Stream transfer into attribute set
           properties.load(proReader);
       }catch (Exception e){
           logger.error(e);
       }

       if(sqlSessionFactory == null){
           synchronized (CLASS_LOCK){
               sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties);
           }
       }
       return sqlSessionFactory;
    }

    /**
     * Open SqlSession
     * @return SqlSession
     */
    public static SqlSession openSqlSesion(){
        // Air handling
        if(sqlSessionFactory == null){
            initSqlSessionFactory();
        }
        return sqlSessionFactory.openSession();
    }
}

Then, the password is encrypted again. When reading, the result set of the reading stream is set persistently
First, encrypt the db.properties database password
After the change, the configuration file is as follows

# Database profile
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://47.94.95.84:32786/mybatis
username = mybatis
password = 8GgwaJCtTXLGItiYF9c4mg==

Then change the Util class again

package com.ming.Util;

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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


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

/**
 * @author ming
 * Build SqlSessionFactory
 * Because the database connection is precious and needs to be managed in a unified way, a single instance is used for management
 * The double lock used by the simple interest here
 * SqlSessionFactory Lock is required for thread unsafe types to ensure that only one thread can use the object at the same time
 */
public class SqlSessionFactoryUtil {

    /**
     * SqlSessionFactory object
     */
    private static SqlSessionFactory sqlSessionFactory = null;

    /**
     * Class thread lock
     */
    private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class;

    /**
     * Log management class
     */
    private static final Logger logger = LogManager.getLogger();
    /**
     * Single case
     */
    private SqlSessionFactoryUtil(){

    }

    /**
     * @return SqlSessionFactory
     * Initialize SqlSessionFactory object
     */
    public static SqlSessionFactory initSqlSessionFactory(){
       // Get input stream
       InputStream cfgStream = null;
       // Reading flow
       Reader cfgReader = null;
       InputStream proStream = null;
       Reader proReader = null;
       // Persistent property set
       Properties properties = null;
       try{
           // Profile flow
           cfgStream = Resources.getResourceAsStream("mybatis-config.xml");
           // Get reading stream
           cfgReader = new InputStreamReader(cfgStream);
           // Read in property file
           proStream = Resources.getResourceAsStream("db.properties");
           proReader = new InputStreamReader(proStream);
           // Persistent property set
           properties = new Properties();
           // Stream load into property set
           properties.load(proReader);
           // Get current system ENV
           String key = System.getenv("KEYWORDES");
           // Decrypt
           properties.setProperty("password", Decode.decryptDecode(properties.getProperty("password"), key));
       }catch (Exception e){
           logger.error(e);
       }

       if(sqlSessionFactory == null){
           synchronized (CLASS_LOCK){
               sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties);
           }
       }
       return sqlSessionFactory;
    }

    /**
     * Open SqlSession
     * @return SqlSession
     */
    public static SqlSession openSqlSesion(){
        // Air handling
        if(sqlSessionFactory == null){
            initSqlSessionFactory();
        }
        return sqlSessionFactory.openSession();
    }
}

Writing unit test

package com.ming.Util;

import org.junit.Test;

import static org.junit.Assert.*;

public class SqlSessionFactoryUtilTest {

    @Test
    public void initSqlSessionFactory() {
    }

    @Test
    public void openSqlSesion() {
        SqlSessionFactoryUtil.openSqlSesion();
    }
}

Current directory structure

At this time, execute unit test, and you can find that unit test has passed
The console prints out the log information

2019-04-11 17:17:37.357 [DEBUG] org.apache.ibatis.logging.LogFactory.setImplementation(LogFactory.java:105) - Logging initialized using 'class org.apache.ibatis.logging.log4j2.Log4j2Impl' adapter.
2019-04-11 17:17:37.403 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections.
2019-04-11 17:17:37.403 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections.
2019-04-11 17:17:37.404 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections.
2019-04-11 17:17:37.404 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections.

Process finished with exit code 0

Error found, modify encryption class

package com.ming.Util;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Base64;

public class Decode {
    /**
     * Generate secret key
     * @param
     * @return
     */
    public static String generateDecode() throws UnsupportedEncodingException {
        KeyGenerator keyGen = null;//key generator 
        try {
            keyGen = KeyGenerator.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyGen.init(56);//Initialize key generator
        SecretKey secretKey = keyGen.generateKey();//Generating key
        byte[] key = secretKey.getEncoded();//Key byte array
        // base64 encoding
        String encodedKey = Base64.getEncoder().encodeToString(key);
        return encodedKey;
    }

    /**
     * Encrypt
     * @param string
     * @param key
     * @return
     */
    public static String encryptionDecode(String string, String key){
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//Recovery key
        Cipher cipher = null;//Cipher completes encryption or decryption work class
        try {
            cipher = Cipher.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);//Initialize Cipher, encryption mode
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        byte[] cipherByte = null;
        try {
            cipherByte = cipher.doFinal(string.getBytes());//Encrypted data
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(cipherByte);
    }

    /**
     * Decrypt
     * @param string
     * @param key
     * @return
     */
    public static String decryptDecode(String string, String key){
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//Recovery key
        Cipher cipher = null;//Cipher completes encryption or decryption work class
        try {
            cipher = Cipher.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.DECRYPT_MODE, secretKey);//Initialize Cipher, decrypt mode
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        byte[] cipherByte = new byte[0];//Decrypt data
        try {
            cipherByte = cipher.doFinal(Base64.getDecoder().decode(string));
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return new String(cipherByte);
    }
}

Run again to find that the sql statement has been executed successfully

Tags: Java Apache Database Mybatis

Posted on Fri, 29 Nov 2019 12:45:15 -0800 by ungown_admin