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

news2024/12/22 1:50:14

项目场景:

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

例如: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 {

    @Override
    public 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.coloradmin.cn/o/2262961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下部署MySQL8.0集群 - 主从复制(一主两从)

目录 一、部署前准备 1、查看系统信息 # 查看系统版本 cat /etc/red* # 查看系统位数 getconf LONG_BIT[rootlocalhost ~]# cat /etc/red* CentOS Linux release 7.5.1804 (Core) [rootlocalhost ~]# getconf LONG_BIT 642、下载对应安装包 进入MySQL官网&#xff1a;https:…

web3跨链桥协议-Nomad

项目介绍 Nomad是一个乐观跨链互操作协议。通过Nomad协议&#xff0c;Dapp能够在不同区块链间发送数据&#xff08;包括rollups&#xff09;&#xff0c;Dapp通过Nomad的合约和链下的代理对跨链数据、消息进行验证、传输。其安全通过乐观验证机制和欺诈证明制约验证者实现&…

【CSS in Depth 2 精译_080】 13.1:CSS 渐变效果(中)——不同色彩空间的颜色插值算法在 CSS 渐变中的应用

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 13 章 渐变、阴影与混合模式】 ✔️ 13.1 渐变 ✔️ 13.1.1 使用多个颜色节点&#xff08;上&#xff09;13.1.2 颜色插值方法&#xff08;中&#xff09; ✔️13.1…

讯飞智文丨一键生成WordPPT

在当今数字化办公的浪潮中&#xff0c;Word和PPT已经成为职场人士日常工作的标配工具。然而&#xff0c;面对繁琐的内容编辑和格式调整任务&#xff0c;如何提升效率成了每个人的追求。而讯飞智文&#xff0c;一款结合人工智能技术的文字处理与演示文稿工具&#xff0c;正逐渐成…

Android Studio的笔记--BusyBox相关

BusyBox 相关 BusyBoxandroid上安装busybox和使用示例一、下载二、移动三、安装和设置环境变量四、使用 busybox源码下载和查看 BusyBox BUSYBOX BUSYBOX链接https://busybox.net/ 点击链接后如图 点击左边菜单栏的Get BusyBix中的Download Source 跳转到busybox 的下载源码…

【机器学习】机器学习的基本分类-强化学习(Reinforcement Learning, RL)

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是一种基于试错的方法&#xff0c;旨在通过智能体与环境的交互&#xff0c;学习能够最大化累积奖励的策略。以下是强化学习的详细介绍。 强化学习的核心概念 智能体&#xff08;Agent&#xff09; 执行动作并与环境…

博世智驾新动力:Apache DolphinScheduler如何征服数据处理挑战

视频及PPT等相关资料&#xff1a;点击查看 讲师介绍 陶超权&#xff0c;博世智驾&#xff08;中国&#xff09;后端工程师&#xff0c;负责数据处理和数据调度方面工作&#xff0c;在智能驾驶数据处理领域具有丰富的实践经验。在2024年12月Apache DolphinScheduler社区线上交流…

令牌(token)+加密(加盐)

目录 一,令牌技术 1,不使用session的原因: 2,有两种解决方案: (1)服务器层面的 (2)客户端层面的(JWT令牌) 生成签名: 生成jwt令牌: 验证令牌是否合法: (3)令牌实际运用 二,加密加盐: 进行加密: 进行验证: 一,令牌技术 1,不使用session的原因: 登录页面,用户会将密…

Flask入门:打造简易投票系统

目录 准备工作 创建项目结构 编写HTML模板 编写Flask应用 代码解读 进一步优化 结语 Flask,这个轻量级的Python Web框架,因其简洁和易用性,成为很多开发者入门Web开发的首选。今天,我们就用Flask来做一个简单的投票系统,让你快速上手Web开发,同时理解Flask的核心概…

阿里巴巴前端面试经验

阿里巴巴面经&#xff08;新零售事业群-CBU技术部&#xff09; 笔试 /*** 1. 查找落单的数字* 描述&#xff1a;给定一个非空的数字数组&#xff0c;数组有且只有一个非重复项&#xff0c;实现一个方法获取落单项* 示例:* getSingleNumber([1, 2, 1, 2, 0]); // 0* getSingle…

指针的深入讲解

本章重点&#xff1a; 字符指针数组指针指针数组数组传参和指针传参函数指针函数指针数组指向函数指针数组的指针回调函数 我们在指针的初阶的时候主要讲了&#xff1a; 1.指针就是变量&#xff0c;用来存放地址&#xff0c;地址唯一标识一块内存空间 2.指针的大小是固定4个…

网络多层的协议详述

网络层 1&#xff09;地址管理&#xff1a;制定一系列的规则&#xff0c;通过地址&#xff0c;在网络上描述出一个设备的位置 2&#xff09;路由选择&#xff1a;网络环境比较复杂&#xff0c;从一个节点到另一个节点&#xff0c;存在很多条不同的路径&#xff0c;需要规划出…

Zabbix6.0升级为6.4

为了体验一些新的功能&#xff0c;比如 Webhook 和问题抑制等&#xff0c;升级个小版本。 一、环境信息 1. 版本要求 一定要事先查看官方文档&#xff0c;确认组件要求的版本&#xff0c;否则版本过高或者过低都会出现问题。 2. 升级前后信息 环境升级前升级后操作系统CentOS…

UML复习题

用例与用户的4种关系对象图和类图有什么关系:对象图是类图某一时刻的快照组件图&#xff0c;体现的是静态图部署图&#xff0c;涉及到硬件的结点&#xff0c;实线链接 以上都是静态图 时序图&#xff0c;消息先后协作图 &#xff0c;谁和谁交互&#xff0c;对象之间的交互某一…

【MFC】多工具栏如何保存状态

MFC中的工具栏本来只有一个&#xff0c;如果想增加几个工具栏是比较简单&#xff0c;但现在一个重要的问题是&#xff0c;状态无法保存&#xff0c;导致每次打开&#xff0c;工具栏就会出现问题&#xff0c;要么偏移位置要么显示不出。 经过研究&#xff0c;发现是MFC框架中的…

Buck开关电源闭环控制的仿真研究15V/5V[Matlab/simulink源码+Word文档]

课题设计要求 ⑴输入直流电压(VIN)&#xff1a;15V ⑵输出电压(VO)&#xff1a;5.0V ⑶负载电阻&#xff1a;R2欧 ⑷输出电压纹波峰-峰值 Vpp≤50mV &#xff0c;电感电流脉动&#xff1a;输出电流的10% ⑸开关频率(fs)&#xff1a;100kHz ⑹BUCK主电路二极管的通态压降VD0.5V…

鸿蒙项目云捐助第十八讲云捐助我的页面下半部分的实现

鸿蒙项目云捐助第十八讲云捐助我的页面下半部分的实现 在一般的应用app中都会有一个“我的”页面&#xff0c;在“我的”页面中可以完成某些设置&#xff0c;也可以完成某些附加功能&#xff0c;如“修改密码”等相关功能。这里的鸿蒙云捐助也有一个“我的”功能页面。这里对“…

Flink2.0未来趋势中需要注意的一些问题

手机打字&#xff0c;篇幅不长&#xff0c;主要讲一下FFA中关于Flink2.0的未来趋势&#xff0c;直接看重点。 Flink Forward Asia 2024主会场有一场关于Flink2.0的演讲&#xff0c;很精彩&#xff0c;官方也发布了一些关于Flink2.0的展望和要解决的问题。 1.0时代和2.0时代避免…

《深入浅出Apache Spark》系列⑤:Spark SQL的表达式优化

导读&#xff1a;随着数据量的快速增长&#xff0c;传统的数据处理方法难以满足对计算速度、资源利用率以及查询响应时间的要求。为了应对这些挑战&#xff0c;Spark SQL 引入了多种优化技术&#xff0c;以提高查询效率&#xff0c;降低计算开销。本文从表达式层面探讨了 Spark…

在Tomcat中部署应用时,如何通过域名访问而不加端口号

--江上往来人&#xff0c;但爱鲈鱼美。 --君看一叶舟&#xff0c;出没风波里。 在Tomcat中部署应用时&#xff0c;如果你希望通过域名访问而不加端口号&#xff08;默认HTTP端口80或HTTPS端口443&#xff09;&#xff0c;你通常需要在前端使用一个反向代理服务器&#xff08;如…