Jackson注解自定义数据脱敏策略

news2024/11/19 1:50:51

Jackson注解自定义数据脱敏策略

  • 1.前言
  • 2.脱敏注解
  • 3.定义好一套需要脱敏的规则
  • 4.自定义JSON序列化
  • 5.在实体类上标注对应的脱敏规则
  • 5.写一个接口进行测试

1.前言

有时候,我们返回给前端的数据需要脱敏,避免用户信息被泄漏,就像你点外卖一样,京东或淘宝购物一样,手机号,姓名这些字段是被脱敏后的,在这个大数据时代,用户的数据安全是及其重要的。我们如何对用户统一数据进行脱敏处理呢?如果我们自定义脱敏方式,使用一个工具类,被改字段传递进去,脱敏后返回新的字符串,那这样是很多地方需要手动去编写很多重复的代码,而且不利于维护,比如是单个bean,或者是list的时候还要去遍历一次list。有没有什么方法统一处理呢?我们定义好脱敏规则,只需要在需要脱敏的字段上加上一个注解即可。那当然是可以的

2.脱敏注解

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.springboot.example.desensitizer.handler.SensitiveJsonSerialize;
import com.springboot.example.desensitizer.enums.SensitiveStrategy ;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 脱敏注解
 * @author compass
 * @date 2022-12-11
 * @since 1.0
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerialize.class)
public @interface Sensitive {

    SensitiveStrategy strategy();
}

3.定义好一套需要脱敏的规则

import java.util.function.Function;

/**
 * 对需要特别脱敏的字段指定脱敏规则
 * @author compass
 * @date 2022-12-11
 * @since 1.0
 **/
public enum SensitiveStrategy {
    /**
     * 对用户名进行脱敏,基于正则表达式实现
     */
    USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),

    /**
     * 对身份证进行脱敏
     */
    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),

    /**
     * 对电话号码进行脱敏
     */
    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),

    /**
     * 对地址进行脱敏
     */
    ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****")),

    /**
     * 对密码进行脱敏,全部加密即可
     */
    PASSWORD(s -> "********");


    private final Function<String, String> desensitizeSerializer;

    SensitiveStrategy(Function<String, String> desensitizeSerializer) {
        this.desensitizeSerializer = desensitizeSerializer;
    }

    // 用于后续获取脱敏的规则,实现脱敏
    public  Function<String, String> desensitizeSerializer() {
        return desensitizeSerializer;
    }


}

4.自定义JSON序列化

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.springboot.example.desensitizer.annotations.Sensitive;
import com.springboot.example.desensitizer.enums.SensitiveStrategy;

import java.io.IOException;
import java.util.Objects;

/**
 * @author compass
 * @date 2022-12-11
 * @since 1.0
 **/
public class SensitiveJsonSerialize  extends JsonSerializer<String> implements ContextualSerializer {

    private SensitiveStrategy strategy;

    // 在序列化时进行数据脱敏
    @Override
    public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        jsonGenerator.writeString(strategy.desensitizeSerializer().apply(value));
    }

    // 获取注解上的属性
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException {
        Sensitive annotation = property.getAnnotation(Sensitive.class);
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
            // 主要代码在这里,获取脱敏的规则
            this.strategy = annotation.strategy();
            return this;
        }
        return provider.findValueSerializer(property.getType(), property);

    }
}

5.在实体类上标注对应的脱敏规则

@Data
@ToString
public class Employee {
    private Long id;

    @Sensitive(strategy = SensitiveStrategy.USERNAME)
    private String name;

    private String email;

    @Sensitive(strategy = SensitiveStrategy.ID_CARD)
    private String identity;

    @Sensitive(strategy = SensitiveStrategy.PASSWORD)
    private String password;

    @Sensitive(strategy = SensitiveStrategy.PHONE)
    private String phone;

    private Date birthday;

    private String jobNumber;

    private Boolean verified;

    @Sensitive(strategy = SensitiveStrategy.ADDRESS)
    private String address;

}

5.写一个接口进行测试

@RestController
@RequestMapping("/sensitiveStrategy")
public class SensitiveStrategyController {

    @GetMapping("/v1/getSensitiveStrategy")
    public ResponseResult<Employee> getSensitiveStrategy() {
        Employee employee = new Employee();
        employee.setId(IdUtil.getSnowflakeNextId());
        employee.setName("诸葛亮");
        employee.setEmail("360369395@qq.com");
        employee.setIdentity("522132188881017455X");
        employee.setPassword("");
        employee.setPhone("17785444960");
        employee.setBirthday(new Date());
        employee.setJobNumber(IdUtil.getSnowflake().nextIdStr());
        employee.setVerified(false);
        employee.setAddress("重庆市沙坪坝区大学城中路2-18号");

        return ResponseResult.success("请求成功", employee);
    }
}

调用我们写的测试接口,可以看到,我们的接口都做了脱敏处理

image-20221211191012694

调用我们写的测试接口,可以看到,我们的接口都做了脱敏处理

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

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

相关文章

node.js安装+卸载,npm+cnpm安装+卸载 vue安装+卸载

node.js安装卸载&#xff0c;npmcnpm安装卸载 vue安装卸载 使用指令整理&#xff1a; #获取node.js版本号&#xff08;验证电脑是否安装&#xff09; node -v #node.js官网地址 #https://nodejs.org/en/ #获取npm版本号&#xff08;npm:Nodejs软件包管理工具)&#xff08;验证…

unix网络编程(四) 线程池并发服务器

线程池并发服务器概念线程池和任务队列任务队列线程池操作线程池的函数初始化线程池销毁线程池向线程池添加任务任务的回调函数测试概念 线程池是一个抽象概念&#xff0c;可以简单的认为若干线程在一起运行&#xff0c;线程不退出&#xff0c;等待有任务处理。 为什么要有线程…

通过选择集获取元素

通过使用内置对象document上的getElementsByTagName方法来获取页面上的某一种标签&#xff0c;获取的是一个选择集&#xff0c;不是数组&#xff0c;但是可以用下标的方式操作选择集里面的标签元素 <!DOCTYPE html> <html lang"en"> <head><me…

Javaweb安全——Weblogic反序列化漏洞(一)

从原生反序列化过程开始谈起。 原生反序列化 序列化就是把对象转换成字节流&#xff0c;便于保存在内存、文件、数据库中&#xff1b;反序列化即逆过程&#xff0c;由字节流还原成对象。 大致是这么一个过程&#xff0c;简单画了个图&#xff1a; 测试类如下&#xff1a; p…

spring mvc——@RequestMapping注解的作用

RequestMapping注解 1、RequestMapping注解的功能 从注解名称上我们可以看到&#xff0c;RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来&#xff0c;建立映射关系。 SpringMVC 接收到指定的请求&#xff0c;就会来找到在映射关系中对应的控制器方法来处理…

从源码编译linux内核并运行一个最小的busybox文件系统

从源码编译linux内核并运行一个最小的busybox文件系统 环境基础&#xff1a; 开发环境&#xff1a;ubuntu 18.04 linux源码版本&#xff1a;linux-4.9.229 busybox源码版本&#xff1a;busybox-1.30.0 qemu-system-x86_64版本&#xff1a;2.0.0 这篇文章将按照如下4个步骤来…

【hexo系列】01.hexo环境搭建及github.io搭建

文章目录基础环境要求安装hexohexo初体验创建hexo工程初体验创建自己的第一篇笔记推送到github网站新建github.io推送到github推送到github(ssh方式 免密)参考资料基础环境要求 检测Node.js是否安装成功&#xff0c;在命令行中输入 node -v 检测npm是否安装成功&#xff0c;在…

机器学习中的数学原理——多重回归算法

这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01;这一篇就更新一下《白话机器学习中的数学——多重回归算法》&#xff01; 目录 一、什么是多重回归 二、案…

物联网开发笔记(60)- 使用Micropython开发ESP32开发板之SPI接口控制Micro SD卡TF卡模块

一、目的 这一节我们学习如何使用我们的ESP32开发板来通过SPI接口控制Micro SD卡TF卡模块。 二、环境 ESP32 SPI接口控制Micro SD卡TF卡模块 Thonny IDE 几根杜邦线 接线方法&#xff1a; Soft SPI接线说明 # 接线说明: # MISO -> GPTO13 # MOSI -> GPIO12 # SCK …

[附源码]Python计算机毕业设计SSM基于的楼盘销售系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SpringCloud入门实战-Ribbon

SpringCloud入门实战-Ribbon使用 原创目录概述需求&#xff1a;设计思路实现思路分析1.Ribbon原理2.Ribbon负载均衡策略参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a bet…

计算机软技术,如何画好一张架构图?

什么是架构图&#xff1f; 如何画好一张架构图&#xff0c;要做好这件事情首先要回答的就是什么是架构图。我们日常工作中经常能看到各种各样的架构图&#xff0c;而且经常会发现大家对架构图的理解各有侧重。深入追究到这个问题&#xff0c;可能一下子还很难有一个具象的定义…

动态路由协议RIP

数据来源 一、动态路由 基于某种协议实现 1&#xff09;动态路由拓补图 2&#xff09;动态路由特点 减少了管理任务占用了网络带宽 3&#xff09;动态路由协议概述 路由器之间用来交换信息的语言 4&#xff09;度量值 跳数、带宽、负载、时延、可靠性、成本 跳数&#xff1a…

JavaScript数据结构【数组---for...of循环迭代】

继for循环&#xff0c;和forEach方法迭代数组后&#xff0c;要想迭代数组的值还可以用for...of循环 使用&#xff1a; // for...of循环示例 let array [1, 2, 3] for (let key of array) {console.log(key); } /* 输出&#xff1a;123 */ 可以看到&#xff1a;使用for...of…

嵌入式介绍与应用

嵌入式介绍与应用1 概念桌面对比2 特点3 发展历史3.1 计算机发展3.2 嵌入式发展4 开发能力要求5 应用6 规模参考1 概念 嵌入式系统由硬件和软件组成。是能够独立进行运作的器件。其软件内容只包括软件运行环境及其操作系统。硬件内容包括信号处理器、存储器、通信模块等在内的…

构建过程:从源码到dist文件

问题 有没有好奇过&#xff0c;自己写的前端代码是怎么变成上线可用的代码的&#xff1f; 前言 目前实现从源码到可用的静态文件&#xff0c;我们都是借助打包工具实现的&#xff0c;目前用的比较多的是webpack、rollup、vite..., 那么以上问题也可以描述为“构建工具是如何…

ChatGPT教程之 03 ChatGPT 中构建 Python 解释器

这个故事的灵感来自于一个类似的故事,在 ChatGPT 中构建虚拟机。我印象深刻并决定尝试类似的东西,但这次不是 Linux 命令行工具,而是让 ChatGPT 成为我们的 Python 解释器。 这是初始化 ChatGPT 的初始命令: I want you to act as a Python interpreter. I will type com…

<<两万字通关Java IO流>>

✨✨hello&#xff0c;愿意点进来的小伙伴们&#xff0c;你们好呐&#xff01; &#x1f43b;&#x1f43b;系列专栏&#xff1a;【JavaEE】 &#x1f432;&#x1f432;本篇内容&#xff1a;详解Java IO流 &#x1f42f;&#x1f42f;作者简介:一名现大二的三非编程小白&#…

python----函数、文件、以及高级特性

文章目录前言一、函数的基本概念二、文件OS模块json模块高级特性生成式生成器闭包装饰器前言 一、函数的基本概念 **全局变量&#xff1a;**在函数外边定义的变量&#xff0c;全局生效 **局部变量&#xff1a;**在函数里边定义的变量&#xff0c;局部生效 如果要在函数中修改全…

【BL808】缘起:M1s开发板的第一个示例-LVGL

一、sipeed M1s介绍 1.1 M1s开发板介绍 1.1.1 开发板特性 板载两个USB口&#xff08;一个用于USB-TTL&#xff0c;一个用于通过模拟U盘的方式烧录c906的固件&#xff09;板载1.69 inch的触摸屏和摄像头接口板载MIC、LED和TF卡座板载一个BL702做成的集USB-TTL和JTAG的调试器。…