Mybatis,实现insert和update时,加密入参

背景

数据库字段内容需要加密,所以才需要给数据库内容加密,因为数据很机密,数据库也不能明文。

思考

	保存和更新的时候,需要给对应的字段内容都给加密,但是这样代码里面的加密,地方需要维护很多代码,很不方便。
就想着写一个统一的方法,来做这件事情。
	在Mybatis执行,insert或者update之前,给需要加密的字段加密。这里就想到了@Intercepts,拦截ParameterHandler.setParameters()方法,在设置参数之前,给对应的入参加密。
		1.标识需要加密的字段
		2.拦截器中,统一给字段数据加密

实现

拦截器代码如下:
import cn.bba.common.utils.SecurityUtil;
import cn.bba.foundation.annotation.ParameterEncrypt;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.MybatisDefaultParameterHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.SQLType;
import java.util.*;

@Slf4j
@Component
@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class),})
public class EncryptInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof MybatisDefaultParameterHandler) {
            MybatisDefaultParameterHandler parameterHandler = (MybatisDefaultParameterHandler) invocation.getTarget();

            try {
                parameterEncrypt(parameterHandler);
            } catch (Exception e) {
                log.error("sql parameter encrypt error!", e);
            }
        }

        return invocation.proceed();
    }

    /**
     * 给参数加密
     */
    private static void parameterEncrypt(MybatisDefaultParameterHandler parameterHandler) throws Exception {
        Field parameterField = parameterHandler.getClass().getDeclaredField("parameterObject");
        parameterField.setAccessible(true);
        // 获取入参
        Object parameterObject = parameterField.get(parameterHandler);

        if (parameterObject != null) {
            Class<?> parameterClass = parameterObject.getClass();
            // 获取方法上面的加密注解 (需要加密字段)
            ParameterEncrypt parameterEncrypt = parameterClass.getAnnotation(ParameterEncrypt.class);
            if (parameterEncrypt != null) {
                for (String fieldStr : parameterEncrypt.fields()) {
                    Field field = parameterClass.getDeclaredField(fieldStr);
                    field.setAccessible(true);
                    Object possField = field.get(parameterObject);
                    if (possField != null) {
                        // List
                        if (possField instanceof List) {
                            List<String> resultList = (ArrayList) possField;
                            List<String> newList = new ArrayList<>();

                            if (CollectionUtils.isNotEmpty(resultList)) {
                                for (String result : resultList) {
                                    // 给入参通过AES加密,再放入
                                    newList.add(SecurityUtil.encryptAes(result));
                                }
                            }
                            possField = newList;
                        } else if (possField instanceof Set) {
                            Set<String> resultList = (HashSet) possField;
                            Set<String> newSet = new HashSet<>();
                            if (CollectionUtils.isNotEmpty(resultList)) {
                                for (String result : resultList) {
                                    // 给入参通过AES加密,再放入
                                    newSet.add(SecurityUtil.encryptAes(result));
                                }
                            }
                            possField = newSet;
                        } else {
                            // 给入参通过AES加密,再放入
                            possField = SecurityUtil.encryptAes(possField.toString());
                        }

                        field.set(parameterObject, possField);
                    }
                }
            }
        }
        // 重新赋值引用
        parameterField.set(parameterHandler, parameterObject);
    }

    /**
     * 切记配置,否则当前拦截器不会加入拦截器链
     */
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    //自定义配置写入,没有自定义配置的可以直接置空此方法
    @Override
    public void setProperties(Properties properties) {
    }
}

注解实现如下:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 需要加密的类,添加此注解,fields,是需要加密的字段
 */
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ParameterEncrypt {
    // 只能添加,String List<String> Set<String> ,字段
    String[] fields() default {};
}

只需要将@ParameterEncrypt,加在需要加密的类中,就可以实现加密

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值