SpringBoot 一个注解实现数据脱敏

什么是数据脱敏

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

数据脱敏通常涉及以下几种主要方法:

  1. 替换: 将原始数据中的敏感信息替换为不敏感的等效数据。例如,将真实姓名替换为随机生成的名称,将电话号码替换为虚构的号码。
  2. 扰动: 对数据进行微小的变化,以使其仍然保持某种程度的统计一致性,但不足以使个人身份可被轻松识别。这包括添加噪声或对数值进行微小的随机化。
  3. 屏蔽: 将敏感信息从数据中删除或隐藏。例如,用特定字符或占位符替换敏感文本。
  4. 一般化: 减少数据的精确度,使得数据更加模糊。例如,将年龄精确到天数的数据一般化为年龄范围。
  5. 删除: 完全删除不必要的敏感信息。

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;}
}

springboot3-数据脱敏

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

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

相关文章

Redis:原理+项目实战——Redis实战1(session实现短信登录(并剖析问题))

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis的Java客户端 &#x1f4da;订阅专栏&#xff1a;Redis速成 希望文章对你们有所帮助…

普中STM32-PZ6806L开发板(HAL库函数实现-PWM呼吸灯)

简介 实现PWM呼吸灯。 主芯片 STM32F103ZET6呼吸灯引脚 : PC7电路原理图 LED8 电路图 LED8 与 主芯片连接图 其他知识 公式 PWM周期公式: Tpwm ( (ARR 1) * (PSC 1) ) / Tclk Tclk为定时器的输入时钟频率 Tout则为定时器溢出时间 ARR为计数周期 PSC为预分频器的值…

[XDCTF 2015]filemanager

[XDCTF 2015]filemanager 我们打开题目&#xff0c;大概看了下存在文件上传功能&#xff0c;并且可以执行重命名和删除文件的操作 扫描目录发现有源码泄露 我们逐一分析 upload.php <?php require_once "common.inc.php";if ($_FILES) {$file $_FILES["…

基于RetinaFace+Jetson Nano的智能门锁系统——第一篇(烧录系统)

文章目录 设备1.首先在PC端安装VMware虚拟机和Ubuntu182.安装VMware Tools3.安装SDK Manager 设备 Jetson NanoMicro-USB - USB-A电源线HDMI线屏幕PC一台 1.首先在PC端安装VMware虚拟机和Ubuntu18 VMware下载地址&#xff1a;https://www.vmware.com/cn/products/workstatio…

软件测试/测试开发丨Windows系统chromedriver安装与环境变量配置

一、selenium 环境配置 1、chrome 浏览器的安装与配置 目前比较常用的浏览器是 Google Chrome 浏览器&#xff0c;所以本教程以 chrome 为主&#xff0c;后面简介一下其他浏览器的环境配置。 &#xff08;1&#xff09;chrome 下载: www.google.cn/chrome/ &#xff08;2&a…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑用户禀赋效应和环保意识不确定性的微电网鲁棒优化调度方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主的专栏栏目《论文与完整程序》 这个标题涉及到微电网系统的优化调度方法&#xff0c;特别考虑了两个重要方面&#xff1a;用户禀赋效应和环保意识的不确定性。以下是对标题中关键术语的解…

代码随想Day55 | 392.判断子序列、115.不同的子序列

392.判断子序列 第一种思路是双指针&#xff0c;详细代码如下&#xff1a; class Solution { public:bool isSubsequence(string s, string t) {//双指针if(s.empty()&&t.empty()) return true;int i0,j0;while(i<t.size()){if(s[j]t[i]) j;if(js.size()) return t…

Springboot整合Elasticsearch 7.X 复杂查询

这里使用Springboot 2.7.12版本&#xff0c;Elasticsearch为7.15.0。 导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency> yaml文件配置…

JAVA反序列化之URLDNS链分析

简单介绍下urldns链 在此之前最好有如下知识&#xff0c;请自行bing or google学习。 什么是序列化 反序列化 &#xff1f;特点&#xff01; java对象反射调用&#xff1f; hashmap在java中是一种怎样的数据类型&#xff1f; dns解析记录有那…

tp5+workman(GatewayWorker) 安装及使用

一、安装thinkphp5 1、宝塔删除php禁用函数putenv、pcntl_signal_dispatch、pcntl_wai、pcntl_signal、pcntl_alarm、pcntl_fork&#xff0c;执行安装命令。 composer create-project topthink/think5.0.* tp5 --prefer-dist 2、配置好站点之后&#xff0c;浏览器打开访问成…

有道翻译web端 爬虫, js

以下内容写于2023-12-28, 原链接为:https://fanyi.youdao.com/index.html#/ 1 在输入框内输入hello world进行翻译,通过检查发出的网络请求可以看到翻译文字的http接口应该是: 2 复制下链接最后的路径,去js文件中搜索下: 可以看到这里是定义了一个函数B来做文字的翻译接口函数…

消息中间件常见知识点

一&#xff1a;消息队列的主要作用是什么&#xff1f; 1.消息队列的特性&#xff1a; 业务无关&#xff0c;一个具有普适性质的消息队列组件不需要考虑上层的业务模型&#xff0c;只做好消息的分发就可以了&#xff0c;上层业务的不同模块反而需要依赖消息队列所定义的规范进行…

如何在2024年编写Android应用程序

如何在2024年编写Android应用程序 本文将介绍以下内容&#xff1a; 针对性能进行优化的单活动多屏幕应用程序 &#x1f92b;&#xff08;没有片段&#xff09;。应用程序架构和模块化 → 每个层面。Jetpack Compose 导航。Firestore。应用程序架构&#xff08;模块化特征驱动…

【C++】STL 容器 - map 关联容器 ③ ( map 容器常用 api 操作 | map 容器迭代器遍历 | map#insert 函数返回值处理 )

文章目录 一、map 容器迭代器遍历1、map 容器迭代器2、代码示例 二、map 容器插入结果处理1、map#insert 函数返回值处理2、代码示例 一、map 容器迭代器遍历 1、map 容器迭代器 C 语言中 标准模板库 ( STL ) 的 std::map 容器 提供了 begin() 成员函数 和 end() 成员函数 , 这…

Seata服务搭建与模式实现

日升时奋斗&#xff0c;日落时自省 目录 1、简述 2、Seata优越性 3、Seata组成 4、Seata模式 4.1、XA 模式 4.2、AT 模式(默认模式) 4.3、TCC 模式 4.4、SAGA 模式 4.5、XA协议 5、Seata服务部署 5.1、文件数据源部署 5.1.1、下载并安装Seata 5.1.2、启动Seata服…

Ts自封装WebSocket心跳重连

WebSocket是一种在单个TCP连接上进行全双工通信的协议&#xff0c;允许客户端和服务器之间进行双向实时通信。 所谓心跳机制&#xff0c;就是在长时间不使用WebSocket连接的情况下&#xff0c;通过服务器与客户端之间按照一定时间间隔进行少量数据的通信来达到确认连接稳定的手…

HarmonyOS4.0系统性深入开发11通过message事件刷新卡片内容

通过message事件刷新卡片内容 在卡片页面中可以通过postCardAction接口触发message事件拉起FormExtensionAbility&#xff0c;然后由FormExtensionAbility刷新卡片内容&#xff0c;下面是这种刷新方式的简单示例。 在卡片页面通过注册Button的onClick点击事件回调&#xff0c;…

数据库中的时间和前台展示的时间不一样,如何保存日期格式的数据到数据库? 如何展示数据库的日期数据到前台

我 | 在这里 &#x1f575;️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 &#x1f3e0; 工作 | 广州 ⭐ Java 全栈开发&#xff08;软件工程师&#xff09; ✈️公众号 | 热爱技术的小郑 文章底部有个人公众号二维码。回复 Java全套视频教程 或 前端全套视频教程 即可获取 300G 教程资料…

【深入浅出RocketMQ原理及实战】「云原生升级系列」打造新一代云原生“消息、事件、流“统一消息引擎的融合处理平台

打造新一代云原生"消息、事件、流"统一消息引擎的融合处理平台 云原生架构RocketMQ的云原生架构实现RocketMQ的云原生发展历程互联网时期的诞生无法支持云原生的能力 云原生阶段的升级云原生升级方向促进了Mesh以及多语言化发展可分合化的存算分离架构存储分离架构的…

听GPT 讲Rust源代码--library/portable-simd

File: rust/library/portable-simd/crates/core_simd/examples/spectral_norm.rs spectral_norm.rs是一个示例程序&#xff0c;它展示了如何使用Portable SIMD库中的SIMD&#xff08;Single Instruction Multiple Data&#xff09;功能来实现频谱规范化算法。该示例程序是Rust源…