springboot3使用​自定义注解+Jackson优雅实现接口数据脱敏

 

⛰️个人主页:     蒾酒

🔥系列专栏:《spring boot实战》

🌊山高路远,行路漫漫,终有归途


目录

写在前面

内容简介

实现思路

实现步骤

1.自定义脱敏注解

2.编写脱敏策略枚举类

3.编写JSON序列化实现

4.编写测试类

5.编写测试接口

6.接口测试

写在最后


写在前面

本文介绍了springboot开发后端服务中,接口数据脱敏优雅的设计与实现,坚持看完相信对你有帮助。

同时欢迎订阅springboot系列专栏,持续分享spring boot的使用经验。

内容简介

本文介绍了一种以优雅的方式实现对接口返回的敏感数据,如手机号、邮箱、身份证等信息的脱敏处理。这种方法也是企业常用方法。话不多说我们一起来看一下吧。

效果展示:

实现思路

  • 自定义一个脱敏注解用于标记需要脱敏的字段,并且在注解中指定脱敏策略属性。
  • 自定义脱敏策略枚举类,用于维护手机号、邮箱、身份证等信息的脱敏处理方式。
  • 自定义脱敏 JSON 序列化器,在该序列化器中找到带有该注解的字段,根据注解中指定的脱敏策略,在序列化过程中将数据进行脱敏处理并输出到 JSON 中。

实现步骤

1.自定义脱敏注解


import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.mijiu.commom.custom.serializable.DesensitizationJsonSerializable;
import com.mijiu.commom.enumerate.DesensitizationStrategyEnum;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author mijiupro*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationJsonSerializable.class)
public @interface Desensitization {DesensitizationStrategyEnum desensitizationStrategy();//这是自定义的脱敏策略枚举类型,用于指定脱敏策略,获取对应脱敏处理方法}

2.编写脱敏策略枚举类

脱敏的本质其实就是个字符串的替换,我们在脱敏策略枚举类中通过定义函数接口,维护多种类型脱敏策略对应的字符串替换方法。这样做可以保证可维护性可扩展性。

import lombok.Getter;import java.util.function.Function;/*** 脱敏策略枚举类,维护对不同类型信息的脱敏处理方式* @author mijiupro*/
@Getter
public enum DesensitizationStrategyEnum {// 手机号脱敏策略,保留前三位和后四位PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),// 邮箱脱敏策略,保留邮箱用户名第一个字符和@符号前后部分EMAIL(s -> s.replaceAll("(\\w)[^@]*(@\\w+\\.\\w+)", "$1****$2")),// 身份证号脱敏策略,保留前四位和后四位ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1*****$2")),// 地址脱敏策略,保留省市信息,其余部分脱敏为**ADDRESS(s -> s.replaceAll("([\\u4e00-\\u9fa5]{2})[\\u4e00-\\u9fa5]+", "$1**")),// 银行卡号脱敏策略,保留前四位和后三位BANK_CARD(s -> s.replaceAll("(\\d{4})\\d{8,12}(\\d{3})", "$1************$2")),// 姓名脱敏策略,保留姓氏第一个字符,其余部分脱敏为**NAME(s -> s.charAt(0) + "**"),// 密码脱敏策略,统一显示为******PASSWORD(s -> "******");private final Function<String, String> desensitization;DesensitizationStrategyEnum(Function<String, String> desensitization) {this.desensitization = desensitization;}}

3.编写JSON序列化实现

需要清楚

  • 平时接口返回的数据结构直接都是交给默认的序列化器把对象转成json的。
  • 实现脱敏的本质就是在这前面添加了一段逻辑,找到带有脱敏注解的属性然后拿到注解指定的脱敏策略实例化这个脱敏策略枚举类,应用对应的脱敏方法处理需要脱敏字段,得到脱敏后的值交给json生成器得到最终脱敏后的json
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.mijiu.commom.annotation.Desensitization;
import com.mijiu.commom.enumerate.DesensitizationStrategyEnum;import java.io.IOException;
import java.util.Objects;/*** 自定义的脱敏JSON序列化器* @author mijiupro*/public class DesensitizationJsonSerializable extends JsonSerializer<String> implements ContextualSerializer {private DesensitizationStrategyEnum desensitizationStrategy; // 脱敏策略@Overridepublic void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {// 将字符串按照设定的脱敏策略进行脱敏处理后序列化到 JSON 中jsonGenerator.writeString(desensitizationStrategy.getDesensitization().apply(s));}@Overridepublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {// 获取属性上的 Desensitization 注解Desensitization annotation = beanProperty.getAnnotation(Desensitization.class);// 判断注解不为空且属性类型为 Stringif (Objects.nonNull(annotation) && Objects.equals(String.class, beanProperty.getType().getRawClass())) {this.desensitizationStrategy = annotation.desensitizationStrategy(); // 设置脱敏策略return this;}// 返回默认的序列化器return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}
}

4.编写测试类

/*** @author mijiupro*/
@Data
@Builder
public class PersonalInfo {@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.PHONE)private String phone; // 手机号@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.EMAIL)private String email; // 邮箱@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.ID_CARD)private String idCard; // 身份证号@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.ADDRESS)private String address; // 地址@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.BANK_CARD)private String bankCard; // 银行卡号@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.NAME)private String name; // 姓名@Desensitization(desensitizationStrategy = DesensitizationStrategyEnum.PASSWORD)private String password; // 密码}

5.编写测试接口

/*** @author mijiupro*/
@RestController
@RequestMapping("/test/desensitization")
@Tag(name = "脱敏测试接口", description = "脱敏测试接口")
public class DesensitizationTestController {@GetMapping("/get-info")@Operation(summary = "获取脱敏信息")public PersonalInfo getInt() {return PersonalInfo.builder().name("言冰云").phone("13812345678").email("mijiu@qq.com").idCard("110101199003073321").address("四川省成都市郫都区百草路一号").password("1234567890").bankCard("62220210001234567890").build();}
}

6.接口测试

这里通过swagger3进行接口测试:

Spring Boot3整合knife4j(swagger3)_springboot3 knife4j-CSDN博客文章浏览阅读2.1k次,点赞39次,收藏52次。Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j (xiaominfo.com)作者的使用的spring boot 3.2.2为当前最新版,所以依赖导入最新的knife4j 4.4.0。3.1 增强模式 | Knife4j (xiaominfo.com)好一个spring boot项目且版本为3X,项目可正常启动。快速开始 | Knife4j (xiaominfo.com)接下来配置以下接口文档的作者等信息。@Tag注解:标记接口类别。_springboot3 knife4jhttps://blog.csdn.net/qq_62262918/article/details/135761392?spm=1001.2014.3001.5502测试结果:

写在最后

springboot3实现优雅的数据脱敏到这里就结束了,本文共列举了实现了七种常见的类型的数据脱敏。任何问题评论区或私信讨论,欢迎指正。

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

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

相关文章

日常刷题之77-组合

题目 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案 提示&#xff1a;假设 n5,k3 就是需要组合出来&#xff0c;长度3且内容数据是在[1,n]这个区间内的所有可能得组合 同时一个组合里面内个数字只能出现一次&#…

在linux中展示本月最后一个周五的日期

写法一 在Linux中&#xff0c;你可以使用date命令结合shell脚本来计算并展示本月最后一个周五的日期。以下是一个简单的bash脚本示例&#xff0c;用于实现这个功能&#xff1a; #!/bin/bash # 获取下个月的第一天 next_month$(date -d "next month" %Y-%m-01) …

亮数据代理IP轻松解决爬虫数据采集痛点

文章目录 一、爬虫数据采集痛点二、为什么使用代理IP可以解决&#xff1f;2.1 爬虫和代理IP的关系2.2 使用代理IP的好处 三、亮数据代理IP的优势3.1 IP种类丰富3.1.1 动态住宅代理IP3.1.2 静态住宅代理IP3.1.3 机房代理IP3.1.4 移动代理IP 3.2 高质量IP全球覆盖3.3 超级代理服务…

如何在Tomcat 9上部署前端和后端项目

在这篇指南中&#xff0c;我们将一步步介绍如何在Apache Tomcat 9服务器上部署一个前端项目&#xff08;我们的示例项目名为“dist”&#xff0c;常见于Vue.js、React等前端框架构建的产物&#xff09;和一个后端Java Web应用程序&#xff08;以WAR包形式&#xff09;。无论您是…

Java标签提高for循环运行效率,减少资源开销

一&#xff0c;Java标签提高for循环运行效率,减少资源开销 少说先看代码再讲解 List<Long> lefts new ArrayList<>(); List<Long> rights new ArrayList<>(); lefts.add(0L); lefts.add(1L); lefts.add(2L); lefts.add(3L); lefts.add(4L); lefts.…

修改Linux系统时间与网络同步

文章目录 1、安装ntpdate2、修改时区3、设置系统时间与网络时间同步4、将系统时间写入硬件时间 1、安装ntpdate # Red Hat和Cent OS系统 sudo yum install ntpdate # 乌班图 sudo apt-get install ntpdate2、修改时区 1&#xff09;运行tzselect tzselect2&#xff09;选择A…

Ubuntu篇——Ubuntu修改网卡优先级

背景&#xff1a;网线接了不能上互联网的局域网&#xff0c;WIFI连了可以上互联网的热点&#xff0c;但是发现上不了网&#xff0c;原因是网线的网卡优先级更高。 用指令临时修改网卡优先级的方法&#xff1a; 1.先看一下网卡基本信息 ip route show 显示内容如下&#xff…

通过socketpair()函数实现同一进程内部的进程间通信(IPC)

在某些情况下&#xff0c;我们可能需要将不同的进程之间进行数据传输或通信&#xff0c;而这些进程又在同一台计算机上运行。使用套接字&#xff08;socket&#xff09;是一种常用的IPC机制。通过创建一对文件描述符&#xff0c;可以在同一进程内模拟两个不同的套接字&#xff…

52、Qt/窗口、常用类、ui相关学习20240321

一、使用Qt 自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面。 要求&#xff1a; 1. 需要使用Ui界面文件进行界面设计 2. ui界面上的组件相关设置&#xff0c;通过代码实现 3. 需要添加适当的动图。 代码&#xff1a; #include "widget.h" #incl…

@Bean和@Component相似与区别

在Spring框架中&#xff0c;Bean和Component都是重要的注解&#xff0c;但它们之间存在一些明显的区别。 首先&#xff0c;它们的用途不同。Component是一个泛化的概念&#xff0c;用于标识一个普通的类&#xff0c;并将其声明为Spring组件。Spring可以扫描到配置了这个注解的…

两台不同账号同一区域阿里云服务器如何实现内网互通?

登录阿里云平台 [开通peer对等] 点击右上角的控制台&#xff0c;然后进行搜索专有网络VPC。 点击进入专有网络VPC界面操作步骤如下&#xff1a; &#xff08;1&#xff09;点击VPC对等连接&#xff0c;然后开通VPC对等连接后创建对等连接。 &#xff08;2&#xff09;在另…

霍夫变换找直线python代码以及从极坐标到笛卡尔坐标的转换

图像霍夫变换找直线 霍夫变换&#xff08;Hough Transform&#xff09;是图像分析中用于检测几何形状&#xff08;如直线、圆等&#xff09;的方法。最常用的是直线检测的霍夫变换&#xff0c;它可以从霍夫空间&#xff08;参数空间&#xff09;到笛卡尔空间&#xff08;图像空…

【计算机】——51单片机——持续更新

单片机是一种内部包含CPU、存储器和输入/输出接口等电路的集成电路&#xff08;IC芯片&#xff09; 单片机是单片微型计算机&#xff08;Single Chip Microcomputer&#xff09;的简称&#xff0c;用于控制领域&#xff0c;所以又称为微型控制器&#xff08;Microcontroller U…

【java基础】Java 的主要特性

Java语言是简单的 ● Java语言的语法与C语言和C语言很接近&#xff0c;使得大多数程序员很容易学习和使用。另一方面&#xff0c;Java丢弃了C中很少使用的、很难理解的、令人迷惑的那些特性&#xff0c;如操作符重载、多继承、自动的强制类型转换。特别地&#xff0c;Java语言不…

038—pandas 重采样线性插补

前言 在数据处理时&#xff0c;由于采集数据量有限&#xff0c;或者采集数据粒度过小&#xff0c;经常需要对数据重采样。在本例中&#xff0c;我们将实现一个类型超分辨率的操作。 思路&#xff1a; 首先将原始数据长度扩展为 3 倍&#xff0c;可以使用 loc[] 方法对索引扩…

OpenCV4.9.0开源计算机视觉库安装教程

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 引言&#xff1a;OpenCV系列文章中的安装部分今天全部完成了&#xff0c;为了读者更方便阅读&#xff0c;大家可以按下列索引前往&#xff0c;成文较为仓促有错漏在所难免&#xff0c;欢迎大家指正…

【C#】使用C#窗体应用开启/停止Apache、MySQL服务

目录 一、前言 二、效果图 三、配置文件 四、代码 五、一键启动/停止所有服务 一、前言 使用C#窗体应用开启Apache、MySQL服务&#xff0c;不仅仅是Apache、MySQL&#xff0c;其他服务也可以使用同样的方法操作&#xff0c;包括开启自己写的脚本服务。 二、效果图 两种状…

JavaSE—IO流之字符流

&#x1f4cc; 字符流中的常用类及基本方法&#xff1a; 输入字符流 Reader输出字符流 Writer ○ Reader 的基本方法&#xff1a; • 读取一个字符并以整数的形式返回, 如果返回-1已到输入流的末尾。 int read() throws IOException • 读取一系列字符并存储到一个数组buff…

BufferedInputStream解读

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java之IO流啦&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好习惯&am…

安卓Java面试题 206- 210

206. 简述如何统计Activity的工作时间 ?如何统计Activity启动所用的时间? 可以通过分析Log得到(这个就是DDMS的那个Log)。 当我们点击触摸时会了类似以下的Log A: 03-06 03:36:47.865: VERBOSE/InputDevice(2486): ID[0]=0(0) Dn (0=>1) 03-06 03:36:47.865: INFO/Powe…