SpringBoot 实现数据脱敏

news2024/11/24 19:41:13

SpringBoot 实现数据脱敏

  • 前言
  • Hutool 实现数据脱敏
    • 引入依赖
    • 脱敏工具类
    • 代码实现
  • 使用注解的方式
    • 定义枚举
    • 自定义序列化类
    • 定义注解
    • 测试

前言

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。

数据脱敏常用规则有替换、重排、加密、截断、掩码

  • 替换:用其他字符或者符号替换原始数据中的字符或者符号,例如将手机号码中间四位替换为星号。
  • 重排:将原始数据中的字符或者符号重新排列,例如将身份证号码中的数字重新排列。
  • 加密:使用加密算法对原始数据进行加密,例如使用AES算法对银行卡号进行加密。
  • 截断:将原始数据中的一部分截取掉,例如只保留姓名的首字母。
  • 掩码:使用特定符号或者字符掩盖原始数据中的一部分,例如使用星号掩盖信用卡号码中的一部分数字。

Hutool 实现数据脱敏

hutool ——一个 Java 基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种 Util 工具类

官方文档:简介 | Hutool

引入依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>

脱敏工具类

hutool 使用信息脱敏工具——DesensitizedUtil 实现脱敏操作

现阶段支持的脱敏数据类型包括:

  1. 用户id
  2. 中文姓名
  3. 身份证号
  4. 座机号
  5. 手机号
  6. 地址
  7. 电子邮件
  8. 密码
  9. 中国大陆车牌,包含普通车辆、新能源车辆
  10. 银行卡

自定义隐藏可以使用StrUtil.hide方法完成

代码实现

public class HutoolDesensitized {
    
    public static void main(String[] args) {
        String phone = "15888888888";
        System.out.println(DesensitizedUtil.mobilePhone(phone)); // 158****8888

        String idCard = "490508200001010001";
        System.out.println(DesensitizedUtil.idCardNum(idCard,4,4)); // 4905**********0001

        String password = "dddd3343ssxx";
        System.out.println(DesensitizedUtil.password(password)); // ************ 对于密码则只保留位数

        String bankCard = "8845600134008139446";
        System.out.println(DesensitizedUtil.bankCard(bankCard)); // 8845 **** **** *** 9446
    }
    
}

使用注解的方式

使用 SpringBoot 自带的 jackson 自定义序列化实现,在 json 进行序列化返回时,实现脱敏

定义枚举

public enum DesensitizationTypeEnum {
    // 自定义
    CUSTOM_RULE,
    // 用户id
    USER_ID,
    // 中文名
    CHINESE_NAME,
    // 身份证号
    ID_CARD,
    // 座机号
    FIXED_PHONE,
    // 手机号
    MOBILE_PHONE,
    // 地址
    ADDRESS,
    // 电子邮件
    EMAIL,
    // 密码
    PASSWORD,
    // 车牌
    CAR_LICENSE,
    //银行卡
    BANK_CARD
}

自定义序列化类

继承JsonSerializer,实现 ContextualSerializer 接口

@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {
    private DesensitizationTypeEnum type;

    private Integer startInclude;

    private Integer endExclude;

    @Override
    public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        switch (type) {
            // 自定义类型脱敏
            case CUSTOM_RULE:
                jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude));
                break;
            // 用户名脱敏
            case USER_ID:
                jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
                break;
            // 中文姓名脱敏
            case CHINESE_NAME:
                jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));
                break;
            // 身份证脱敏
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 4, 4));
                break;
            // 固定电话脱敏
            case FIXED_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
                break;
            // 手机号脱敏
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));
                break;
            // 地址脱敏
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));
                break;
            // 邮箱脱敏
            case EMAIL:
                jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));
                break;
            // 密码脱敏
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));
                break;
            // 中国车牌脱敏
            case CAR_LICENSE:
                jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));
                break;
            // 银行卡脱敏
            case BANK_CARD:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));
                break;
            default:
        }

    }

    @Override
    public 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);
                // 为null
                if (desensitization == null) {
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                // 不为null
                if (desensitization != null) {
                    // 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。
                    return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),
                            desensitization.endExclude());
                }
            }

            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}

定义注解

@JsonSerialize 定义 json 序列化器

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {
    /**
     * 脱敏数据类型,在 CUSTOM_RULE 的时候,startInclude 和 endExclude 生效
     */
    DesensitizationTypeEnum type() default DesensitizationTypeEnum.CUSTOM_RULE;

    /**
     * 脱敏开始位置(包含)
     */
    int startInclude() default 0;

    /**
     * 脱敏结束位置(不包含)
     */
    int endExclude() default 0;
}

测试

定义一个测试类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestUser {

    @Desensitization(type = DesensitizationTypeEnum.MOBILE_PHONE)
    private String phone;

    @Desensitization(type = DesensitizationTypeEnum.EMAIL)
    private String email;

    @Desensitization(type = DesensitizationTypeEnum.CUSTOM_RULE,startInclude = 3, endExclude = 9)
    private String customEntity;
}

测试接口

@RestController
@RequestMapping
public class TestController {

    @GetMapping("/test")
    public TestUser testDesensitization() {
        TestUser testUser = new TestUser();
        testUser.setPhone("15888888888");
        testUser.setEmail("dadfd_333@163.com");
        testUser.setCustomEntity("dfkdjf3434__495kdjf@@");
        return testUser;
    }
}

返回数据

image-20231008201531787

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

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

相关文章

接口测试和性能测试的区别

最近我在一个论坛上看到了一个关于性能测试和接口测试的经典问题&#xff0c;问题如下&#xff1a; 问题&#xff1a;后端性能测试&#xff0c;一个功能其实都是由后台多个接口组成的。 例如一个单据的保存&#xff0c;可能后台需要调用几个接口。用LR录制这个功能做性能测试。…

Java如何进行数据脱敏

1.SQL数据脱敏实现 MYSQL(电话号码,身份证)数据脱敏的实现 1 2 3 4 5 6 7 8 -- CONCAT()、LEFT()和RIGHT()字符串函数组合使用&#xff0c;请看下面具体实现 -- CONCAT(str1,str2,…)&#xff1a;返回结果为连接参数产生的字符串 -- LEFT(str,len)&#xff1a;返回从字符串st…

Vue Router的进阶

进阶 导航守卫 官方文档上面描述的会比较深奥&#xff0c;而守卫类型也比较多&#xff0c;其中包含了全局前置守卫、全局解析守卫、全局后置钩子、路由独享守卫、组件内守卫。每一种守卫的作用和用法都不相同。这会使得大家去学习的时候觉得比较困难&#xff0c;这边主要介绍…

如何平衡需求的优先级冲突?

每个项目都有各种需求&#xff0c;如业务需求、技术需求、用户需求、系统需求。我们需要对这些需求进行优先级排序&#xff0c;平衡不同利益相关者的需求&#xff0c;以更好满足客户需求&#xff0c;确保关键业务目标得到优先满足&#xff0c;并合理分配资源&#xff0c;避免资…

移植 NetXDuo 到 STM32F4 芯片

移植 NetXDuo 到 STM32F4 芯片 1. NetXDuo 和 ThreadX 源码获取2. 准备工作2.1 基本工程模板获取 —— CubeMx 3.ThreadX 移植3.1 添加到工程3.2 文件修改3.3 补充完成回调函数 4. NetXDuo 移植4.1 将 NetXDuo 添加到工程4.2 驱动层实现4.3 测试 1. NetXDuo 和 ThreadX 源码获取…

RT-Thread 中断管理(学习二)

中断的底半处理 RT-Thread不对中断服务程序所需要的处理时间做任何假设、限制&#xff0c;但如同其它实时操作系统或非实时操作系统一样&#xff0c;用户需要保证所有的中断服务程序在尽可能短的时间内完成。这样在发生中断嵌套&#xff0c;或屏蔽了相应中断源的过程中&#x…

小黑开始了拉歌训练,第一次进入部室馆,被通知要去当主持人心里有些紧张的leetcode之旅:337. 打家劫舍 III

小黑代码&#xff08;小黑卡在了bug中&#xff0c;上午一步步探索做出&#xff0c;非常NB!!!&#xff09; # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left lef…

Hive窗口函数回顾

1.语法 1.1 基于行的窗口函数 Hive的窗口函数分为两种类型&#xff0c;一种是基于行的窗口函数&#xff0c;即将某个字段的多行限定为一个范围&#xff0c;对范围内的字段值进行计算&#xff0c;最后将形成的字段拼接在该表上。 注意&#xff1a;在进行窗口函数计算之前&#…

X86指令基本格式

X86指令基本格式 1 什么是机器码2 X86指令基本格式3 指令前缀3.1 第一组&#xff1a;封锁和重复执行前缀3.2 第二组&#xff1a;段前缀3.3 第三组&#xff1a;修改操作数默认长度3.4 第四组&#xff1a;修改默认地址长度 4 操作码5 ModR/M与SIB5.1 ModR/M字节5.2 SIB字节 6 地址…

uCharts常用图表组件demo

带渐变阴影的曲线图 <view class"charts-box"><qiun-data-charts type"area" :opts"opts" :chartData"chartData" :ontouch"true":background"rgba(256,256,256,0)" /> </view>data(){return{…

嵌入式学习(1)HAL库

文章目录 1.HAL库文件介绍2.HAL库编程目录结构3.使用cubemx生成HAL库编程目录结构 1.HAL库文件介绍 2.HAL库编程目录结构 3.使用cubemx生成HAL库编程目录结构

【JavaEE重点知识归纳】第7节:类和对象

目录 一&#xff1a;了解面向对象 1.什么是面向对象 2.面向对象和面向过程区分 二&#xff1a;类定义和使用 1.什么是类 2.练习&#xff1a;定义一个学生类 三&#xff1a;类的实例化 1.什么是实例化 2.类和对象的说明 四&#xff1a;认识this 1.为什么要有this引用…

rails 常量自动加载和重新加载机制

在Rails中&#xff0c;有一个称为"常量自动加载和重新加载机制"的功能&#xff0c;它使得在开发和生产环境中能够自动加载和重新加载类和模块。这个机制允许您不必手动管理类的加载&#xff0c;使得开发更加方便。 快乐学习&#xff1a; 自动加载、重新加载 自动加…

Yii2全拦截路由catchAll的使用

定义&#xff1a;catchAll 路由&#xff08;全拦截路由&#xff09; 应用场景&#xff1a;网站维护的时候需要向用户抛出一个维护的页面&#xff0c;方便提醒用户 使用方法&#xff1a; 1、在应用配置中设置 yii\web\Application::catchAll 属性 2、新增对应的控制器方法 3、…

【Putty】win10 / win 11:SSH 远程连接工具 Putty 下载、安装

目录 一、Jmerter 连接 SSH 隧道的 mysql&#xff08;不可行&#xff09; 二、Putty 介绍 三、Putty 的下载 四、Putty 无需安装直接使用 五、Putty 使用 &#xff08;1&#xff09;我需要连接 ssh 隧道的 MySQL 参数如下 &#xff08;2&#xff09;Putty 使用教程 一、…

MA-SAM:模态不可知的三维医学图像分割SAM自适应

论文&#xff1a;MA-SAM: Modality-agnostic SAM Adaptation for 3D Medical Image Segmentation | Papers With Code 代码&#xff1a;GitHub - cchen-cc/MA-SAM: PyTorch implementation for MA-SAM 机构&#xff1a;a)高级医疗计算和分析中心&#xff0c;麻省总医院和哈佛…

华为云开源低代码引擎 TinyEngine 正式发布

随着企业对于低代码开发平台的需求日益增长,急需一个通用的解决方案来满足各种低代码平台的开发需求。正是在这种情况下,低代码引擎应运而生。它是一种通用的开发框架,通过对低代码平台系统常用的功能进行解构,将其划分为多个功能模块,并为每个模块定义了相应的协议和开发…

Go 语言中 panic 和 recover 搭配使用

本次主要聊聊 Go 语言中关于 panic 和 recover 搭配使用 &#xff0c;以及 panic 的基本原理 最近工作中审查代码的时候发现一段代码&#xff0c;类似于如下这样&#xff0c;将 recover 放到一个子协程里面&#xff0c;期望去捕获主协程的程序异常 看到此处&#xff0c;是否会…

传输层TCP协议

前言 传输层的历史渊源可以追溯到计算机网络的早期阶段。在20世纪60年代和70年代&#xff0c;计算机网络主要是由一些简单的点对点连接组成的。这些连接通常使用专用的硬件和协议&#xff0c;例如串行线路和电话线路。在这种情况下&#xff0c;传输层的功能是由这些协议本身来提…

【SpringCloud】认识微服务

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 认识微服务 一、 服务架构演变1.1 单体架构…