使用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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM