Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题

server/2024/12/24 4:18:43/

项目场景:

提示:这里简述项目相关背景:

例如:Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题


问题描述

提示:这里描述项目中遇到的问题:

例如:数据传输过程中数据不时出现丢失的情况,偶尔会丢失一部分数据
APP 中接收数据代码:

public Object intercept(Invocation invocation) throws Throwable {ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();// 获取传入的参数对象Object parameterObject = parameterHandler.getParameterObject();if (parameterObject instanceof Map) {Map<?, ?> paramMap = (Map<?, ?>) parameterObject;for (Map.Entry<?, ?> entry : paramMap.entrySet()) {Object key = entry.getKey();Object value = entry.getValue();// 对于带有 @Sensitive 注解的字段,进行加密处理if (value != null && !value.toString().isEmpty()) {  // 判空和空字符串检查// 反射检查该字段是否标记了 @Sensitive 注解if (isSensitiveField(value)) {String encryptedValue = SensitiveDataUtils.encrypt(value.toString(), SM4_KEY);((Map<Object, Object>) paramMap).put(key, encryptedValue);}}}} else {// 处理非 Map 类型的参数(如单个对象查询)encryptSensitiveFields(parameterObject);}// 执行原始逻辑return invocation.proceed();}
这个方法有问题啊

原因分析:

提示:这里填写问题的分析:

是的,这个 intercept 方法存在几个潜在问题,可能导致在处理加密字段时出现错误。以下是详细的分析和改进建议:

  1. parameterObject 为 Map 类型时的处理
    在你当前的代码中,如果 parameterObject 是 Map 类型,会迭代其中的 key-value 对并检查每个 value 是否标记了 @Sensitive 注解,进而进行加密处理。这里有几个潜在问题:

value 可能是复杂对象:目前的判断条件是 if (value != null && !value.toString().isEmpty()),但是 value 可能是一个复杂对象(例如 User 对象),而不是一个简单的 String 类型。在这种情况下,直接使用 value.toString() 可能并不能反映实际字段的内容。

isSensitiveField 反射问题:你尝试通过反射检查 value 是否包含 @Sensitive 注解,但是 value 很可能是一个普通的 Java 对象(如 AdminUserDO),直接传给 isSensitiveField 可能会导致反射错误。

  1. parameterObject 不是 Map 类型时的处理
    如果 parameterObject 不是 Map 类型,你使用 encryptSensitiveFields(parameterObject) 来处理加密。该方法会检查对象中的字段并加密被 @Sensitive 注解标记的字段。问题在于,你并没有考虑 parameterObject 可能是一个嵌套对象,或者该对象的类型可能没有适当的 getter 方法,导致反射出错。

  2. 改进建议
    我们需要确保在处理 Map 类型和非 Map 类型的参数时,都能正确处理嵌套对象和字段加密。


解决方案:

提示:这里填写该问题的具体解决方案:

package cn.iocoder.yudao.framework.mybatis.core.handler;import cn.iocoder.yudao.framework.annotation.Sensitive;
import cn.iocoder.yudao.framework.mybatis.core.util.SensitiveDataUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.Map;import static cn.iocoder.yudao.framework.mybatis.core.util.SensitiveDataUtils.SM4_KEY;@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})
})
public class SensitiveDataEncryptInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();// 获取传入的参数对象Object parameterObject = parameterHandler.getParameterObject();// 如果是 Map 类型的参数if (parameterObject instanceof Map) {Map<?, ?> paramMap = (Map<?, ?>) parameterObject;for (Map.Entry<?, ?> entry : paramMap.entrySet()) {Object key = entry.getKey();Object value = entry.getValue();// 判断 value 是否为带有 @Sensitive 注解的字段,进行加密处理if (value != null) {// 对 value 进行加密String encryptedValue = encryptSensitiveValue(value);// 如果字段需要加密,替换 Map 中的值if (encryptedValue != null) {// 强制转换为 Map<Object, Object> 来避免类型问题((Map<Object, Object>) paramMap).put(key, encryptedValue);}}}} else {// 如果不是 Map 类型,处理对象的字段加密encryptSensitiveFields(parameterObject);}// 执行原始逻辑return invocation.proceed();}private String encryptSensitiveValue(Object value) throws Exception {if (value instanceof String && isSensitiveField(value)) {// 对象字段加密处理return SensitiveDataUtils.encrypt(value.toString(), SM4_KEY);}return null;}private boolean isSensitiveField(Object value) {// 判断该对象字段是否带有 @Sensitive 注解Class<?> clazz = value.getClass();for (Field field : clazz.getDeclaredFields()) {if (field.isAnnotationPresent(Sensitive.class)) {return true;  // 该字段带有 @Sensitive 注解}}return false;}private void encryptSensitiveFields(Object parameterObject) throws Exception {// 遍历对象的字段,检查是否带有 @Sensitive 注解Field[] fields = parameterObject.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(Sensitive.class)) {field.setAccessible(true);Object value = field.get(parameterObject);if (value != null) {String encryptedValue = SensitiveDataUtils.encrypt(value.toString(), SM4_KEY);field.set(parameterObject, encryptedValue);}}}}
}

主要改进点:

encryptSensitiveValue 方法:

这个方法首先检查传入的 value 是否是需要加密的字段,如果是,则进行加密。
通过调用 isSensitiveField(value) 来判断是否需要加密,而不直接依赖 value.toString()。

isSensitiveField 方法:

通过反射检查 value 对象是否包含带有 @Sensitive 注解的字段。之前可能存在错误的反射逻辑,这里是基于对象字段的反射检查。

encryptSensitiveFields 方法:

遍历 parameterObject 的字段,并加密带有 @Sensitive 注解的字段。处理对象字段时,直接通过反射获取字段并进行加密。
其他注意事项:
确保 SensitiveDataUtils.encrypt 方法能够正确处理所有类型的 value,尤其是对于非 String 类型的对象,可能需要进一步优化加密处理。
如果 parameterObject 是一个复杂的对象,确保该对象的所有字段都可以通过反射访问(即字段为 public 或者使用了 setAccessible(true))。
这样修改后,应该能够有效避免反射错误并正确处理加密逻辑。


http://www.ppmy.cn/server/152664.html

相关文章

React 工具和库面试题(一)

1. 如何在 React 项目中使用 Hooks 从服务端获取数据&#xff1f; 在 React 中&#xff0c;我们通常使用 useEffect Hook 来进行副作用操作&#xff0c;比如从服务端获取数据&#xff0c;结合 useState 来管理数据状态。 基本步骤&#xff1a; 使用 useEffect 来执行异步操作…

git 怎么删除一个远程分支

在Git中&#xff0c;删除远程分支是一个相对简单的操作。以下是删除远程分支的步骤&#xff1a; 打开命令行工具&#xff1a; 打开你的命令行工具&#xff08;如Terminal、Git Bash、Cmder等&#xff09;。 切换到你的仓库&#xff1a; 使用cd命令切换到你的Git仓库目录。 检…

基于Linux编写C语言基础命令

目录 一、常用的Linux命令 1、改变及显示目录命令&#xff1a;cd、pwd、ls。 1.1、cd&#xff08;Change Directory&#xff09; 1.2、pwd&#xff08;Print Working Directory&#xff09; 1.3、ls&#xff08;List&#xff09; 2、文件及目录的创建、复制、删除和移动命…

【蓝桥杯】43688-《Excel地址问题》

Excel地址问题 题目描述 Excel 单元格的地址表示很有趣&#xff0c;它可以使用字母来表示列号。比如&#xff0c; A 表示第 1 列&#xff0c; B 表示第 2 列&#xff0c; … Z 表示第 26 列&#xff0c; AA 表示第 27 列&#xff0c; AB 表示第 28 列&#xff0c; … BA 表示…

stm32制作CAN适配器5--WinUsb上位机编写

上次我们要stm32制作了一个基于winusb有canfd适配器&#xff0c;今天我们来制作一个上位机程序来进行报文收发。 上位机还是用以前写好的&#xff0c;只是更改下dll文件。 项目链接器&#xff0c;输入&#xff0c;附加依赖项中增加winusb.lib winusb初始化&#xff1a;#incl…

【CSS in Depth 2 精译_085】14.2:CSS 蒙版的用法

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 14 章 蒙版、形状与剪切】 ✔️ 14.1 滤镜 14.1.1 滤镜的类型14.1.2 背景滤镜 14.2 蒙版 ✔️ 14.2.1 带渐变效果的蒙版特效 ✔️14.2.2 基于亮度来定义蒙版 ✔️14…

【NVIDIA】启动ubuntu后显卡驱动丢失

前言 启动后分辨率变成800*600&#xff0c;而且不能改&#xff0c;nvidia-smi 显示 这种情况可以先不用着急重装&#xff1b; 执行 ls /usr/src | grep nvidia显示英伟达驱动版本 nvidia-565.57.01再 sudo dkms install -m nvidia -v 565.57.01就好了&#xff5e;&#xf…

cocos creator制作2dTop-down游戏(虚拟摇杆、地图加载)

《不被遗忘的时光》第一期 1、游戏的形式&#xff1a;横板&#xff1b;2d的顶视角&#xff08;Top-down&#xff09;&#xff1b;射击&#xff1b;ARPG&#xff1b;益智解谜。 2、画风&#xff1a;类似手游《伊洛纳》。 3、故事背景&#xff1a;以中元节的爷孙阴阳交流作为故…