mybatis自制插件+注解实现数据脱敏

欢迎来到我的博客,代码的世界里,每一行都是一个故事


在这里插入图片描述

mybatis自制插件+注解实现数据脱敏

    • 前言
    • 数据脱敏的实现方式
    • 构思
      • 从哪个地方进行脱敏?
      • 它怎么知道我什么数据需要脱敏
    • 项目实现
      • 拦截器实现
      • 注解实现
      • 枚举实现
      • 效果图展示

前言

在数字时代,数据安全问题备受关注。想象一下,你的应用程序可能在处理各种敏感信息,例如用户的身份证号码、银行卡号等。如果这些信息泄露,后果不堪设想!但别担心,今天我们将揭开 MyBatis 数据脱敏的神秘面纱,让你的数据像戴着隐形护甲一样安全。

数据脱敏的实现方式

我认为数据脱敏主要可分为两种情况。首先,是在数据入库时进行脱敏处理,这意味着在存储之前就对敏感数据进行加密,比如可以使用类似于密码盐加密的方式进行加密。第二种情况是在从数据库查询出数据后进行脱敏处理。在这种情况下,脱敏的位置可以灵活选择,可以在查询结果立即脱敏,也可以在控制器层面进行脱敏处理。举例来说,可以利用AOP在方法执行后执行脱敏逻辑。这里我主要讲的是第二种中的查询结果立即脱敏。

构思

从哪个地方进行脱敏?

首先对于mybatis来说,它其实也是遵守像传统的JDBC操作的,只不过它在这其中点了几朵花。具体来说也就是下面的几步:

  1. Class.forName注册驱动
  2. 获取一个Connection对象
  3. 创建一个Statement对象
  4. execute()方法执行SQL语句,获取ResultSet结果集
  5. 通过ResultSet结果集给POJO的属性赋值
  6. 最后关闭相关的资源

通过上面的,我们就能知道我们需要拦截的位置了,也就是在ResultSet结果集那里,在mybatis中也就是org.apache.ibatis.executor.resultset.ResultSetHandler#handleResultSets方法

具体来说,ResultSetHandler 是 MyBatis 中的一个接口,它定义了数据库查询结果集处理的方法。其中,handleResultSets 方法用于处理从数据库返回的结果集。在 MyBatis 中,查询结果可以是单个对象、对象列表或映射,而 handleResultSets 方法则负责将这些查询结果转换为 Java 对象或集合。

它怎么知道我什么数据需要脱敏

在1的基础上我们需要明白,如何找到你标记为脱敏的数据,以及你如何标记脱敏。多想一步的话,我们就应该知道,我们脱敏的可能目前仅仅有手机号,身份证号,但是保不准以后就会有别的了,而且单纯的在拦截器中根据字段名称编码也不现实,于是就有了注解,比如对于user表中的phone我们需要脱敏,那么只需要在实体类的这个字段下加个注解即可

项目实现

这里我就不再过多的赘述了,直接贴代码

拦截器实现

package com.todoitbo.baseSpringbootDasmart.interceptor;import com.todoitbo.baseSpringbootDasmart.annotation.Desensitize;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.Properties;/*** @author xiaobo*/
@Intercepts({@Signature(type = ResultSetHandler.class,method = "handleResultSets",args = {Statement.class}
)})
@Component
public class DesensitizeInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 执行结果处理前的逻辑Object result = invocation.proceed();// 对结果进行脱敏处理if (result instanceof List) {List<?> list = (List<?>) result;for (Object obj : list) {desensitize(obj);}} else {desensitize(result);}return result;}private void desensitize(Object obj) {if (obj == null) {return;}Field[] fields = obj.getClass().getDeclaredFields();for (Field field : fields) {// 检查字段上是否存在Desensitize注解if (field.isAnnotationPresent(Desensitize.class)) {Desensitize desensitize = field.getAnnotation(Desensitize.class);try {// 私有字段可以访问field.setAccessible(true);Object value = field.get(obj);if (value instanceof String) {// 字段脱敏String desensitizedValue = desensitize.type().desensitize((String) value);// 设置脱敏后的值field.set(obj, desensitizedValue);}} catch (IllegalAccessException e) {// 处理异常}}}}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 可以通过配置文件传入参数}
}

注解实现

package com.todoitbo.baseSpringbootDasmart.annotation;import com.todoitbo.baseSpringbootDasmart.Enum.DesensitizeType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author xiaobo*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Desensitize {// 定义脱敏策略,可以扩展更多类型DesensitizeType type() default DesensitizeType.PHONE;
}

枚举实现

package com.todoitbo.baseSpringbootDasmart.Enum;import java.util.function.Function;/*** @author todoitbo* @date 2024/4/12*/
// 脱敏策略枚举
public enum DesensitizeType {PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),EMAIL(s -> s.replaceAll("(\\w+)\\w{3}@(\\w+)", "$1***@$2"));// ...其他脱敏类型private final Function<String, String> desensitizer;DesensitizeType(Function<String, String> desensitizer) {this.desensitizer = desensitizer;}public String desensitize(String value) {return desensitizer.apply(value);}private String desensitizeValue(String value, DesensitizeType type) {return type.desensitize(value);}// 可以添加更多的脱敏类型
}

如果你追求特别完美,或者极致,你也可以优化上面的代码,具体从以下几点优化:

  1. 预编译正则表达式:
    • 每次调用desensitize方法时,都会创建一个新的正则表达式模式。
    • 预编译正则表达式,并将它们作为Pattern对象存储,可以减少正则表达式编译的开销。
  2. 减少lambda表达式创建的开销:
    • 每个枚举实例都会创建一个lambda表达式。
    • 可以考虑将脱敏逻辑移到一个静态方法中,并在枚举构造器里引用这个方法,减少lambda表达式的创建。
  3. 避免不必要的对象创建:
    • 如果传入的字符串不需要脱敏,或者已经是脱敏后的格式,可以直接返回原字符串,避免创建新的字符串对象。

效果图展示

image-20240412182811545

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817403.shtml

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

相关文章

hive了解系列一

“ 随着智能手机的普及&#xff0c;互联网时代红利的爆发&#xff0c;用户数量和产生的数据也越发庞大。为了解决这个问题&#xff0c;提高数据的使用价值。 Hadoop生态系统就被广泛得到应用。 在早期&#xff0c;Hadoop生态系统就是为处理如此大数据集而产生的一个合乎成本效益…

力扣第20题有效的括号

typedef char STDataType; //动态栈 #define allocator_may_return_null 1typedef struct ST {STDataType* _a;int _top;//栈顶元素int _capacity;//最大容量 }Stack; //初始化栈 void StackInit(Stack *pst);//入栈 void StackPush(Stack* pst, STDataType x);//出栈 void Sta…

小程序变更主体需要多久?

小程序迁移变更主体有什么作用&#xff1f;小程序迁移变更主体的好处有很多哦&#xff01;比如可以获得更多权限功能、公司变更或注销时可以保证账号的正常使用、收购账号后可以改变归属权或使用权等等。小程序迁移变更主体的条件有哪些&#xff1f;1、新主体必须是企业主体&am…

每日OJ题_BFS解决最短路①_力扣1926. 迷宫中离入口最近的出口

目录 力扣1926. 迷宫中离入口最近的出口 解析代码 力扣1926. 迷宫中离入口最近的出口 1926. 迷宫中离入口最近的出口 难度 中等 给你一个 m x n 的迷宫矩阵 maze &#xff08;下标从 0 开始&#xff09;&#xff0c;矩阵中有空格子&#xff08;用 . 表示&#xff09;和墙&…

Scrapy 框架基础

Scrapy框架基础Scrapy框架进阶 Scrapy 框架基础 【一】框架介绍 【1】简介 Scrapy是一个用于网络爬取的快速高级框架&#xff0c;使用Python编写他不仅可以用于数据挖掘&#xff0c;还可以用于检测和自动化测试等任务 【2】框架 官网链接https://docs.scrapy.org/en/late…

WPS二次开发系列:WPS SDk功能就概览

作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 作者通过深度测试使用了WPS SDK提供的Demo&#xff0…

ThreadX在STM32上的移植:通用启动文件tx_initialize_low_level.s

在嵌入式系统开发中&#xff0c;实时操作系统&#xff08;RTOS&#xff09;的选择对于系统性能和稳定性至关重要。ThreadX是一种广泛使用的RTOS&#xff0c;它以其小巧、快速和可靠而闻名。在本文中&#xff0c;我们将探讨如何将ThreadX移植到STM32微控制器上&#xff0c;特别是…

#381. 四边形继承练习

太爽了 甚至还现学了叉积判断线段是否相交和求面积的方法 先给出我的代码&#xff1a; #include <iostream> #include <vector> #include <iomanip> #include <cmath>using namespace std;//下面需要补充多个类的声明及实现代码 const double EPS 1…

创新营销利器:淘宝扭蛋机小程序开发全解析

在数字化浪潮的推动下&#xff0c;淘宝扭蛋机小程序的开发成为了一种全新的购物体验。它巧妙地将传统扭蛋机的乐趣与移动技术的便捷相结合&#xff0c;为用户带来了前所未有的惊喜与互动。 淘宝扭蛋机小程序的开发&#xff0c;不仅是一次技术的革新&#xff0c;更是一次购物方…

【基于HTML5的网页设计及应用】——事件代理.

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

gcn代码处理出现的问题

README 版本不一致 python 2.7 PYTHON 3.7 切换 TensorFlow系统的学习使用 数据集下载

每个人都可以做一个赚钱的社群

如何创建并运营一个赚钱的社群 一、引言 大家好&#xff0c;今天&#xff0c;我想和大家分享一下如何创建并运营一个赚钱的社群。我的分享目的是希望能够持续输出有价值的内容。 二、心态建设 1. 重要性&#xff1a;创业心态与平常心 在开始社群运营之前&#xff0c;我们需…

在线知识库如何从零开始搭建?这篇文章来教你!

引言&#xff1a; 有没有想过把那些零散在脑海中的点点滴滴整理起来&#xff0c;建立一个属于自己的在线知识库&#xff1f;无论是个人学习&#xff0c;团队协作&#xff0c;还是企业管理&#xff0c;一个良好的知识库都能帮我们更高效地存储和分享知识。如果你还在为“怎么建知…

持续上榜!赛宁网安多项能力入选《中国网络安全行业全景图》

4月12日&#xff0c;国内网安咨询机构安全牛正式发布《中国网络安全行业全景图》第十一版。赛宁网安凭借在网络安全领域前沿的技术创新优势、丰富的实践经验积累以及专业的综合安全服务&#xff0c;入选此次全景图安全支撑技术与体系的安全靶场领域、安全管理与运营的BAS领域和…

docker特殊问题处理3——docker-compose安装配置nacos

最近几年随着大数据和人工智能持续大热&#xff0c;容器化安装部署运维已经走进了各个中小公司&#xff0c;也得已让众多开发者能上手实际操作&#xff0c;不过说真心话&#xff0c;“万物皆可容器化”的理念越来越深入人心。 而如何使用docker-compose安装&#xff0c;配置&a…

Windows下安装GPU版Pytorch

升级Driver到最新版本 Windows搜索栏中输入设备管理器找到显示适配器一项&#xff0c;点击展开&#xff0c;你将看到你的NVIDIA显卡列在其中右键点击你的NVIDIA显卡&#xff0c;选择更新驱动软件…。在弹出的对话框中&#xff0c;选择自动搜索更新的驱动软件。之后&#xff0c…

html--烟花3

html <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Canvas烟花粒子</title> <meta name"keywords" content"canvas烟花"/> <meta name"description" content"can…

股票开户佣金最低多少?万一!A股开户多少钱合适?

开户佣金 通常情况下&#xff0c;股票开户佣金只要在达成交易的前提才收手续的费用&#xff0c;即买入和卖出的时候。目前&#xff0c;国规定收取最高佣金的比例为千分之三。 也就是说&#xff0c;最高为成交金额的3%&#xff0c;一般都会小于这个比例。最低交易佣金是5元起&a…

如何为不同内容主题选择最适合的移动滑轨屏方案?

在数字化信息时代背景下&#xff0c;多媒体互动装置作为当前内容展示的常用手段&#xff0c;颇受大众的喜爱&#xff0c;比如应用在展厅、商业推广、活动会议等领域的滑轨屏&#xff0c;便是其中一种新颖的互动展示装置&#xff0c;并且它还能根据不同的内容主题&#xff0c;来…

2024年文化、历史与人文艺术与社会发展国际会议(CHHASD2024)

2024年文化、历史与人文艺术与社会发展国际会议(CHHASD2024) 会议简介 2024年国际文化、历史、人文、艺术与社会发展会议&#xff08;CHHASD2024&#xff09;将在中国武汉举行&#xff0c;主题为“文化、历史&#xff0c;人文、艺术和社会发展”。CHHASD2024汇集了来自世界各…