mybatis-plus实现数据字段加解密

目录

1、对称加解密工具类

2、拦截器

2.1、解密拦截器

2.2、加密拦截器

3、注解

3.1、EncryptedField

3.2、EncryptedTable

4、使用实例


1、对称加解密工具类

package com.demo.modules.desensitization;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import com.demo.modules.desensitization.annotation.EncryptedField;
import com.demo.modules.desensitization.annotation.EncryptedTable;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
/**
 * @title 对称加解密工具类
 * @description 主要用于mybatis拦截器中加解密字段
 * @author: Wanglei
 * @create 2024/4/12 0012 18:39:40
 */
public class EncryptDecryptUtils {

    private static final byte[] KEYS = "Apa987^%$321c2mp".getBytes(StandardCharsets.UTF_8);
    /**
     * 对指定的对象进行加密处理。
     * 该方法首先获取对象的类信息,然后检查该类是否被@EncryptedTable注解标记。如果被标记,
     * 则遍历该类的所有字段,对这些需要加密的字段进行加密处理。
     *
     * @param parameterObject 需要进行加密处理的对象。该对象的类必须被@EncryptedTable注解标记。
     * @throws IllegalAccessException 如果在访问字段时发生访问权限问题,则抛出此异常。
     */
    public static void doEncrypt(Object parameterObject) throws IllegalAccessException{
        if(ObjectUtil.isEmpty(parameterObject)){
            return;
        }
        // 获取传入对象的类信息
        Class<?> parameterObjectClass = parameterObject.getClass();
        // 尝试查找该类上的@EncryptedTable注解
        EncryptedTable encryptDecryptClass = AnnotationUtils.findAnnotation(parameterObjectClass, EncryptedTable.class);
        if (Objects.nonNull(encryptDecryptClass)){
            // 获取类中所有声明的字段
            Field[] declaredFields = parameterObjectClass.getDeclaredFields();
            // 对所有字段进行加密处理
            encrypt(declaredFields, parameterObject);
        }
    }
    /**
     * 多field加密方法
     *
     * @param declaredFields
     * @param parameterObject
     * @param <T>
     * @return
     * @throws IllegalAccessException
     */
    public static <T> T encrypt(Field[] declaredFields, T parameterObject) throws IllegalAccessException {
        for (Field field : declaredFields) {
            EncryptedField annotation = field.getAnnotation(EncryptedField.class);
            if (Objects.isNull(annotation)) {
                continue;
            }
            encrypt(field, parameterObject);
        }
        return parameterObject;
    }


    /**
     * 单个field加密方法
     *
     * @param field
     * @param parameterObject
     * @param <T>
     * @return
     * @throws IllegalAccessException
     */
    public static <T> T encrypt(Field field, T parameterObject) throws Ill
### MyBatis-Plus 敏感字段加密实现方法 #### 一、引入必要的依赖 为了在 MyBatis-Plus实现敏感字段的加密,首先需要确保项目中包含了 AES 加密所需的依赖。通常情况下,在 `pom.xml` 文件中添加如下依赖即可[^2]。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 如果使用的是非 Spring Boot 项目,则需单独加入 BouncyCastle 或其他支持 AES 的库 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>最新版本号</version> </dependency> ``` #### 二、创建加解密工具类 定义一个用于执行实际加解密工作的工具类,该类负责提供统一接口来完成对指定字符串类型的敏感数据进行加密和解密操作。下面是一个简单的例子: ```java import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AesUtil { private static final String ALGORITHM = "AES"; public static SecretKey generateKey() throws Exception { KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM); keyGen.init(128); // 可选参数长度为128, 192或256位 return keyGen.generateKey(); } public static byte[] encrypt(String content, SecretKey secretKey) throws Exception { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return Base64.getEncoder().encode(cipher.doFinal(content.getBytes())); } public static String decrypt(byte[] encryptedContent, SecretKey secretKey) throws Exception { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); return new String(cipher.doFinal(Base64.getDecoder().decode(encryptedContent))); } } ``` #### 三、自定义插件拦截器 通过继承 `AbstractSqlInjector` 类并重写其中的方法来自定义 SQL 注入逻辑,从而可以在每次插入/更新记录前自动调用上述工具类来进行加密处理;而在查询时则相反地先解码再返回给业务层消费。具体做法是在项目的启动类上注册此插件实例[^3]。 ```java @Component @Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class EncryptInterceptor extends AbstractSqlInjector implements Interceptor { @Override protected void injectMap(MappedStatement ms, Class<?> mapperClass, Method method, Object... params) throws Throwable { super.injectMap(ms, mapperClass, method, params); MetaObject metaObject = SystemMetaObject.forObject(params[0]); if (metaObject.hasGetter("sensitiveData")){ // 判断是否存在名为'sensitiveData'属性 String originalValue = (String) metaObject.getValue("sensitiveData"); try{ SecretKey secretKey = AesUtil.generateKey(); // 获取秘钥对象 if ("insert".equals(method.getName()) || "updateById".equals(method.getName())) { byte[] encryptedBytes = AesUtil.encrypt(originalValue, secretKey); metaObject.setValue("sensitiveData", encryptedBytes); }else if("selectOne".equals(method.getName())){ String decryptedStr=AesUtil.decrypt((byte[])originalValue,secretKey ); metaObject.setValue("sensitiveData",decryptedStr ); } }catch(Exception e){ throw new RuntimeException(e.getMessage(),e.getCause()); } } } } ``` 以上就是关于如何利用 MyBatis-Plus 结合 Java 内置的安全机制(如 JCE)以及第三方安全组件(比如 BC 库),轻松达成数据库层面的数据保护目标的整体思路介绍[^1]。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕山石头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值