SpringBoot 一个注解实现数据脱敏
什么是数据脱敏
数据脱敏是指对某些敏感信息,例如姓名、身份证号码、手机号、固定电话、银行卡号、邮箱等个人信息,通过脱敏算法进行数据变形,以保护敏感隐私数据。

数据脱敏通常涉及以下几种主要方法:
- 替换: 将原始数据中的敏感信息替换为不敏感的等效数据。例如,将真实姓名替换为随机生成的名称,将电话号码替换为虚构的号码。
- 扰动: 对数据进行微小的变化,以使其仍然保持某种程度的统计一致性,但不足以使个人身份可被轻松识别。这包括添加噪声或对数值进行微小的随机化。
- 屏蔽: 将敏感信息从数据中删除或隐藏。例如,用特定字符或占位符替换敏感文本。
- 一般化: 减少数据的精确度,使得数据更加模糊。例如,将年龄精确到天数的数据一般化为年龄范围。
- 删除: 完全删除不必要的敏感信息。
Spring Boot自定义注解实现数据脱敏
依赖版本
- JDK 17
- Spring Boot 3.2.0
- Hutool-core 5.8.24 (非必须)
源码地址:Gitee
导入依赖
<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>5.8.24</version></dependency>
</dependencies>
自定义脱敏类型枚举
/*** @description 数据脱敏策略枚举*/
public enum DesensitizationTypeEnum {//自定义CUSTOM,//用户idUSER_ID,//中文名CHINESE_NAME,//身份证号ID_CARD,//座机号FIXED_PHONE,//手机号MOBILE_PHONE,//地址ADDRESS,//电子邮件EMAIL,//密码PASSWORD,//中国大陆车牌,包含普通车辆、新能源车辆CAR_LICENSE,//银行卡BANK_CARD
}
自定义脱敏序列化器
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.yiyan.study.annotation.Desensitization;
import com.yiyan.study.enums.DesensitizationTypeEnum;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;import java.io.IOException;
import java.util.Objects;/*** @description 自定义脱敏序列化类*/
@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {private DesensitizationTypeEnum type;private Integer startInclude;private Integer endExclude;@Overridepublic void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {switch (type) {// 自定义类型脱敏case CUSTOM -> jsonGenerator.writeString(CharSequenceUtil.hide(String.valueOf(str), startInclude,endExclude >= startInclude ? endExclude : str.length() + endExclude));// userId脱敏case USER_ID -> jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));// 中文姓名脱敏case CHINESE_NAME -> jsonGenerator.writeString(CharSequenceUtil.hide(String.valueOf(str), 1, str.length()));// 身份证脱敏case ID_CARD -> jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 1, 2));// 固定电话脱敏case FIXED_PHONE -> jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));// 手机号脱敏case MOBILE_PHONE -> jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));// 地址脱敏case ADDRESS -> jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));// 邮箱脱敏case EMAIL -> jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));// 密码脱敏case PASSWORD -> jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));// 中国车牌脱敏case CAR_LICENSE -> jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));// 银行卡脱敏case BANK_CARD -> jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));}}@Overridepublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {if (beanProperty != null) {// 判断数据类型是否为String类型if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {// 获取定义的注解Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);if (desensitization == null) {desensitization = beanProperty.getContextAnnotation(Desensitization.class);}if (desensitization != null) {return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),desensitization.endExclude());}}return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}return serializerProvider.findNullValueSerializer(null);}
}
自定义脱敏注解
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.yiyan.study.enums.DesensitizationTypeEnum;
import com.yiyan.study.serialize.DesensitizationSerialize;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 脱敏注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {/*** 脱敏数据类型,CUSTOM注解下,startInclude和endExclude生效*/DesensitizationTypeEnum type() default DesensitizationTypeEnum.CUSTOM;/*** 脱敏开始位置(包含)*/int startInclude() default 0;/*** 脱敏结束位置(不包含)*/int endExclude() default 0;
}
数据脱敏测试
定义测试对象
import com.yiyan.study.annotation.Desensitization;
import com.yiyan.study.enums.DesensitizationTypeEnum;
import lombok.Builder;
import lombok.Data;import java.io.Serializable;@Data
@Builder
public class DesensitizationDTO implements Serializable {@Desensitization(type = DesensitizationTypeEnum.CHINESE_NAME)private String username;@Desensitization(type = DesensitizationTypeEnum.EMAIL)private String email;@Desensitization(type = DesensitizationTypeEnum.ADDRESS)private String address;@Desensitization(type = DesensitizationTypeEnum.MOBILE_PHONE)private String phoneNumber;@Desensitization(type = DesensitizationTypeEnum.CUSTOM, startInclude = 1, endExclude = -2)private String note;
}
测试接口
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yiyan.study.model.DesensitizationDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 启动类*/
@SpringBootApplication
@Slf4j
@RestController
public class DesensitizationApplication {private static final DesensitizationDTO dto = com.yiyan.study.model.DesensitizationDTO.builder().username("小李").phoneNumber("12300000456").email("li@gmail.com").address("XX.YY.DD.FF").note("123456789").build();public static void main(String[] args) throws JsonProcessingException {SpringApplication.run(DesensitizationApplication.class, args);ObjectMapper mapper = new ObjectMapper();String s = mapper.writeValueAsString(dto);log.info("Json : {}", s);}@GetMapping("/test")public DesensitizationDTO desensitizationTest() {return dto;}
}

相关文章:
SpringBoot 一个注解实现数据脱敏
什么是数据脱敏 数据脱敏是指对某些敏感信息,例如姓名、身份证号码、手机号、固定电话、银行卡号、邮箱等个人信息,通过脱敏算法进行数据变形,以保护敏感隐私数据。 数据脱敏通常涉及以下几种主要方法: 替换: 将原始…...
记录:开始学习网络安全
本文持续更新学习进度 背景 在私企干了5年虚拟化、云原生相关的运维,学到了很多,但不成体系。老板是清华毕业法国留学在德勤干过,最后回国创业的野路子。我工作是为了更好的生活,我挺担心老板因为家庭变故或者炒个原油宝&#x…...
C语言—第1次作业:编译与连接基础知识
常做练习巩固知识 本次作业答案链接如下: 答案解析——C语言—第1次作业:编译与连接基础知识 1.字符串的结束标志是:( ) A.是0 B.是EOF C. 是\0 D.是空格 2.关于C语言关键字说法正确的是:( ) A.关…...
not attached to window manager问题解决
关于出现这个问题,一般是因为Activity已经在finish了,但是还在dialog.show(),或者dialog.dismiss().导致window manager无法管理dialog。解决办法如下: /** * 20210913 安全关闭对话框 . * 避免报:not attac…...
影视后期: PR调色处理,调色工具面板介绍
写在前面 整理一些影视后期的相关笔记博文为 Pr 调色处理,涉及调色工具面板简单认知包括 lumetri 颜色和范围面板理解不足小伙伴帮忙指正 元旦快乐哦 _ 名词解释 饱和度 是指色彩的鲜艳程度,也被称为色彩的纯度。具体来说,它表示色相中灰色…...
ARM AArch64的虚拟化(virtualization)详解(上)
目录 一、概述 开始之前 二、虚拟化介绍 为什么虚拟化很重要...
计算机组成原理知识总结
目录 第一章、计算机系统概述知识框架:1.冯诺依曼机和存储程序的概念?2.计算机的工作过程?3.在计算机系统结构中,什么是编译?什么是解释?4.描述一下指令执行过程?1) 取指令: PC 一&g…...
springboot学习(八十五) 解决springboot3.2找不到资源无法抛出404错误的问题
前言 springboot3.2以下可以定义ErrorPageRegistrar将404错误转发到一个接口地址,但升级到springboot3.2(spring6.1)后,该配置不生效,抛出了500错误。 以前的错误页面处理如下: ConditionalOnClass(ErrorPageRegist…...
OpenHarmony 应用通用签名
一.背景 由于hap包需要经过签名才能安装到设备上,在DevEco Studio可以进行自动签名,但是自动签名只能安装在当前的设备上,在其他设备上不能安装,所以我们需要进行通用的手动签名,手动签名HarmonyOS和OpenHarmony流程是…...
Redis:原理+项目实战——Redis实战1(session实现短信登录(并剖析问题))
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理速成项目实战——Redis的Java客户端 📚订阅专栏:Redis速成 希望文章对你们有所帮助…...
交叉编译aarch64架构支持openssl的curl、libcurl
本文档旨在指导读者在x86_64平台上交叉编译curl和openssl库以支持aarch64架构。在开始之前,请确保您的系统环境已正确配置。 1. 系统环境准备 系统是基于Ubuntu 20.04 LTS,高版本可能会有问题。首页,安装必要的开发工具和库文件。打开终端并…...
扩展名是.KEY的文件可能有不同的存在,打开方式也因此不同
本文解释了使用KEY文件扩展名的所有不同格式,以及如何在可能的情况下打开和转换每种格式。 KEY文件的定义 KEY文件扩展名可能是用于注册软件程序的纯文本或加密的通用许可证密钥文件。不同的应用程序使用不同的KEY文件来注册各自的软件,并证明用户是合…...
软件工程总复习笔记
软件工程课程复习提纲 文章目录 软件工程课程复习提纲一、基本知识点1. 软件工程的概念及目标2. 软件危机的概念及典型表现3. 瀑布模型的概念及特点4. 快速原型模型的特点5. 螺旋模型的基本思想6. 软件生命周期的概念及划分为哪几个阶段7. 软件需求的定义8. 常见的软件需求获取…...
蓝桥杯-每日刷题-030
打印等边三角形 一、题目要求 题目描述 输出等边三角形:输入n值,输出高度为n的等边三角形。输入格式 输入存在多组测试数据。对于每组测试数据输入一个正整数n(1<n<100)。输出格式 对于每组测试数据输出对应的等边三角形。每组测试数据最后输出一…...
AI赋能游戏开发,如何更好地处理随之而来的海量数据,更好地利用开发游戏?
人工智能(AI)正在改变我们所知的游戏行业。它为3A工作室、独立开发者和业余爱好者提供了工具,让他们能够更轻松地创建以前需要大量时间和资源的项目。尤其是,虚幻引擎的AI工具已经取得了显著的进步。 虚幻引擎AI拥有专门用于游戏…...
Serverless架构学习路线及平台对比
在云计算领域,Serverless架构已经成为了一个重要的趋势。本文将为你提供一条清晰的Serverless架构学习路线,帮助你系统地掌握这个领域的知识,并对比国内外的Serverless平台的优缺点。 一、基础理论学习 首先,我们需要理解Server…...
解决ROS含动态参数的Config文件无法正确识别的错误
问题描述 功能包名为paddle_detection 在工作空间下, 通过catkin_make可以正常通过编译且执行无异常, 可以通过bloom-generate rosdebian生成依赖 但是在将其打包成deb包的过程中fakeroot debian/rules binary报错 fatal error: paddle_detection/paddle_detectionConfig.…...
探索 PyTorch 中的 torch.nn 模块**(1)
目录 引言 torch.nn使用和详解 Parameter 函数作用 使用技巧 使用方法和示例 UninitializedParameter 特点和用途 可进行的操作 使用示例 UninitializedBuffer 特点和用途 可进行的操作 使用示例 Module**(重点) 关键特性和功能 举例说…...
【WPF.NET开发】预览事件
本文内容 先决条件预览标记为“已处理”的事件通过控件解决事件禁止问题 预览事件,也称为隧道事件,是从应用程序根元素向下遍历元素树到引发事件的元素的路由事件。 引发事件的元素在事件数据中报告为Source 。 并非所有事件场景都支持或需要预览事件。…...
JDBC->SpringJDBC->Mybatis封装JDBC
一、JDBC介绍 Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
