Throw away the tool class. Mybatis has a simple configuration for data encryption and decryption

Click on "end of life", pay attention to the official account.

Daily technical dry goods, delivered at the first time!

Preface: introduce a simple MyBatis encryption and decryption method. Few people mention this method in their daily study and work, so let's talk about it. If you already know this method, ignore this article!

1. Background

Sometimes in our database, some sensitive information of users, such as mobile phone number, bank card and other information, will be saved. If these information is saved in clear text, it is not safe. If hackers hack into the database, or resigned personnel export data, it may lead to the leakage of these sensitive data. Therefore, we need to find a way to solve this problem.

2. Solution

Since Mybatis is used as the database persistence layer in our system, we decided to use Mybatis's TypeHandler or Plugin to solve the problem.

typeHandler: we need to manually specify typeHandler on some columns to choose which typeHandler to use, or infer from @ MappedJdbcTypes} and @ MappedTypes} annotations.

<result column="phone" property="phone" typeHandler="com.huan.study.mybatis.typehandler.EncryptTypeHandler"/>

Plugin: it can intercept statements such as select, insert, update and delete in the system, and obtain parameters before and data after sql execution.

After consideration, we decided to use TypeHandler to encrypt and decrypt data.

3. Demand

We have a customer table customer, which contains fields such as customer phone number and customer address. The customer phone number needs to be encrypted and saved in the database.

1. When adding customer information, the customer's mobile phone number is automatically encrypted and saved in the data.

2. When querying customer information, automatically decrypt the customer's mobile phone number.

4. Realization idea

1. Write an entity class. All the data of this entity class represents the data that needs to be encrypted and decrypted

public class Encrypt {
    private String value;

    public Encrypt() {
    }

    public Encrypt(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

2. Write an encryption and decryption TypeHandler

  • When setting parameters, encrypt data.

  • Decrypt the data when getting records from the database.

/**
 * Encryption and decryption TypeHandler
 *
 * @author huan.fu 2021/5/18 - 9:20 am
 */
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Encrypt.class)
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {

    private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);

    /**
     * Set parameters
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null || parameter.getValue() == null) {
            ps.setString(i, null);
            return;
        }
        AES aes = SecureUtil.aes(KEYS);
        String encrypt = aes.encryptHex(parameter.getValue());
        ps.setString(i, encrypt);
    }

    /**
     * Get value
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName));
    }

    /**
     * Get value
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex));
    }

    /**
     * Get value
     */
    @Override
    public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex));
    }

    public Encrypt decrypt(String value) {
        if (null == value) {
            return null;
        }
        return new Encrypt(SecureUtil.aes(KEYS).decryptStr(value));
    }
}

be careful:

  • @MappedTypes: indicates what java types the processor handles.

  • @MappedJdbcTypes: indicates the type of Jdbc processed by the processor.

3. Writing in sql statement

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huan.study.mybatis.mappers.CustomerMapper">

    <resultMap id="BaseResultMapper" type="com.huan.study.mybatis.entity.Customer">
        <id column="id" property="id"/>
        <result column="phone" property="phone"/>
        <result column="address" property="address"/>
    </resultMap>

    <insert id="addCustomer">
        insert into customer(phone,address) values (#{phone},#{address})
    </insert>

    <select id="findCustomer" resultMap="BaseResultMapper">
        select * from customer where phone = #{phone}
    </select>

</mapper>

There is no special way to write in SQL.

4. The package path of the Typehandler specified in the configuration file

mybatis.type-handlers-package=com.huan.study.mybatis.typehandler

5. Write background code

  • Provides an add method

  • Provide a method to query according to the mobile phone number

The background code is relatively simple. You can view it directly:

https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt

Post a screenshot of the mapper layer.

6. Test results

It can be seen from the test results that when adding data, the data (phone) to be encrypted has been encrypted in the database, and the encrypted data has been automatically decrypted when querying.

5. Implementation code

https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt

PS: in case you can't find this article, you can collect some likes for easy browsing and searching

Keywords: Java Back-end

Added by itarun on Fri, 07 Jan 2022 08:05:04 +0200