SpringBoot3使用​自定义注解+Jackson实现接口数据脱敏的步骤

 更新时间:2024年03月26日 10:38:19   作者:蒾酒  
本文介绍了一种以优雅的方式实现对接口返回的敏感数据,如手机号、邮箱、身份证等信息的脱敏处理,这种方法也是企业常用方法,话不多说我们一起来看一下吧

写在前面

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

内容简介

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

效果展示:

实现思路

  • 自定义一个脱敏注解用于标记需要脱敏的字段,并且在注解中指定脱敏策略属性。
  • 自定义脱敏策略枚举类,用于维护手机号、邮箱、身份证等信息的脱敏处理方式。
  • 自定义脱敏 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; // 脱敏策略
 
    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        // 将字符串按照设定的脱敏策略进行脱敏处理后序列化到 JSON 中
        jsonGenerator.writeString(desensitizationStrategy.getDesensitization().apply(s));
    }
 
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        // 获取属性上的 Desensitization 注解
        Desensitization annotation = beanProperty.getAnnotation(Desensitization.class);
 
        // 判断注解不为空且属性类型为 String
        if (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进行接口测试:

springboot3整合knife4j详细图文教程(swagger增强)_java_脚本之家 (jb51.net)

测试结果:

写在最后

springboot3实现优雅的数据脱敏到这里就结束了,本文共列举了实现了七种常见的类型的数据脱敏。

以上就是SpringBoot3使用​自定义注解+Jackson实现接口数据脱敏的步骤的详细内容,更多关于SpringBoot3接口数据脱敏的资料请关注脚本之家其它相关文章!

相关文章

  • Java 中ThreadLocal类详解

    Java 中ThreadLocal类详解

    什么是ThreadLocal?顾名思义它是local variable(线程局部变量)。它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。
    2016-03-03
  • java设计模式之委派模式原理分析

    java设计模式之委派模式原理分析

    这篇文章主要介绍了java设计模式之委派模式原理分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • SpringBoot自带模板引擎Thymeleaf使用示例详解

    SpringBoot自带模板引擎Thymeleaf使用示例详解

    Thymeleaf是一款用于渲染XML/HTML5内容的模板引擎,类似JSP,它可以轻易的与SpringMVC等Web框架进行集成作为Web应用的模板引擎,本文给大家介绍SpringBoot自带模板引擎Thymeleaf使用示例,感兴趣的朋友一起看看吧
    2023-12-12
  • SpringBoot使用Shiro实现动态加载权限详解流程

    SpringBoot使用Shiro实现动态加载权限详解流程

    本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 、 按钮 、uri 权限后,后端动态分配权限,用户无需在页面重新登录才能获取最新权限,一切权限动态加载,灵活配置
    2022-07-07
  • SpringMVC HttpMessageConverter报文信息转换器

    SpringMVC HttpMessageConverter报文信息转换器

    这篇文章主要为大家介绍了SpringMVC HttpMessageConverter报文信息转换器,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Java并发CopyOnWrite容器原理解析

    Java并发CopyOnWrite容器原理解析

    这篇文章主要介绍了Java并发CopyOnWrite容器原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Java 流的高级使用之收集数据解析

    Java 流的高级使用之收集数据解析

    这篇文章主要介绍了Java 流的高级使用之收集数据解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java selenium上传文件的实现

    Java selenium上传文件的实现

    本文主要介绍了Java selenium上传文件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Mybatis枚举类型转换源码分析

    Mybatis枚举类型转换源码分析

    在Mybatis的TypeHandlerRegistry中,添加了常用的类转换器,其中默认的枚举类型转换器是EnumTypeHandler,这篇文章主要介绍了Mybatis枚举类型转换源码分析,需要的朋友可以参考下
    2024-05-05
  • SpringBoot整合Mybatis自定义拦截器不起作用的处理方案

    SpringBoot整合Mybatis自定义拦截器不起作用的处理方案

    这篇文章主要介绍了SpringBoot整合Mybatis自定义拦截器不起作用的处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09

最新评论