使用mybatis的BaseTypeHandler来给敏感字段进行AES加密

开发中,公司会要求对敏感字段进行加密处理后入库,查询的时候需要解密后展示,这就要求原字符串和加密字符串之间进行转换

如果一两个字符串还好,可以直接在入库的时候和查询的时候处理一下,但是如果有很多字段都需要这样处理怎么办?

Mybatis里面有一个TypeHandler可以解决这个问题,只需要在需要加密/解密的字段上使用@TableField(typeHandler = AesTypeHandler.class),

包含该字段的实体上使用@TableName(autoResultMap = true)即可(PS:AesTypeHandler是自定义的TypeHandler)

为了方便,这里我们使用的是Hutool的AES加密工具

首先导入依赖

 <dependency>
       <groupId>cn.hutool</groupId>
       <artifactId>hutool-all</artifactId>
       <version>5.5.8</version>
 </dependency>

然后创建AesUtil加密工具

package com.qjc.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import org.apache.commons.lang3.StringUtils;

public class AESUtil {
    private static final String AES_KEY = "AES_KEY";

    private static final byte[] KEY_BYTES;

    private static String keyStr = "ad1725339b2dd0a68903c57b635942ca";

    static {
        KEY_BYTES = new byte[16];
        int i = 0;
        for (byte b : keyStr.getBytes()) {
            KEY_BYTES[i++ % 16] ^= b;
        }
    }

    public static String encrypt(String content) {
        if (StringUtils.isBlank(content)) {
            return content;
        }
        return HexUtil.encodeHexStr(SecureUtil.aes(KEY_BYTES).encrypt(content), false);
    }

    public static String decrypt(String content) {
        if (StringUtils.isBlank(content)) {
            return content;
        }
        return SecureUtil.aes(KEY_BYTES).decryptStr(content);
    }

    public static void main(String[] args) {
        String encrypted = encrypt("测试");
        System.out.println(encrypted);
        System.out.println(decrypt(encrypted));
    }
}

定义AesTypeHandler

package com.qjc.config;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.qjc.utils.AESUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/** 数据库中的数据类型 */
@MappedJdbcTypes(JdbcType.VARCHAR)
/** 处理后的数据类型 */
@MappedTypes(value = String.class)
public class AesTypeHandler extends BaseTypeHandler {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, AESUtil.encrypt((String) parameter));
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return StringUtils.isBlank(rs.getString(columnName)) ? rs.getString(columnName) : AESUtil.decrypt(rs.getString(columnName));
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return StringUtils.isBlank(rs.getString(columnIndex)) ? rs.getString(columnIndex) : AESUtil.decrypt(rs.getString(columnIndex));
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return StringUtils.isBlank(cs.getString(columnIndex)) ? cs.getString(columnIndex) : AESUtil.decrypt(cs.getString(columnIndex));
    }
}

然后再实体和字段上添加注解

package com.qjc.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;

import java.time.LocalDateTime;

import com.qjc.config.AesTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;


@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "t_user", autoResultMap = true)
public class TUser extends Model {

    private static final long serialVersionUID = 1L;

    @TableId("id")
    private Long id;

    @TableField(typeHandler = AesTypeHandler.class)
    private String name;

    private String address;

    private Integer age;

    private LocalDateTime createTime;

    private LocalDateTime updateTime;


}

测试

@Test
    public void test() {
        TUser user = new TUser();
        user.setName("用户");
        user.setAge(18);
        user.setAddress("地址");
        userMapper.insert(user);
    }

插入数据

 查询数据

mysql中直接用HEX(AES_ENCRYPT(str,key_str))函数生成加密串就行,和工具AESUtil生成的加密串是一致的。mysql中解密AES字符串AES_DECRYPT(UNHEX(str),key_str)

劈天造陆,开辟属于自己的天地!!!与君共勉
原文地址:https://www.cnblogs.com/java-spring/p/14676670.html