java后端数据脱敏看这一篇就够了.

简介: 现在的项目中需要对展示的数据进行脱敏处理,类似的场景很常见,比如说展示的手机号、银行卡、用户姓名等全部用***这类的特殊字符进行代替。

背景说明


   现在的项目中需要对展示的数据进行脱敏处理,类似的场景很常见,比如说展示的手机号、银行卡、用户姓名等全部用***这类的特殊字符进行代替。我们的项目就需要将岗位展示列表中的用户岗位发布姓名全部用星号进行替换.最初的时候是入门级版本,几行代码就可以实现。后期对项目进行优化,考虑到脱敏的场景以及脱敏的形式可能会变化(比如说手机号脱敏要求前面三位后两位之外的进行脱敏,用户姓名要求全部脱敏处理),所以对原有逻辑进行了修改,于是有了进阶版实现方式,优点在于对脱敏业务与序列化处理进行解耦,便于拓展和后期维护,下面就具体说下处理过程,希望对有同样需求的同学有所帮助!


入门级处理


   场景:将岗位查询列表中的用户姓名进行全部脱敏处理,使用三个星号进行代替.直接上代码:

实体类ShopPostInfo:

public class ShopPostInfo implements Serializable {
    private static final long serialVersionUID = -2040496864515327697L;
    // 数据脱敏处理,用户名全部替换为***
   @JsonSerialize(using = DesensitizationSerializer.class)
    private String userName;
// 省略其他信息


自定义脱敏处理器DesensitizationSerializer:

public class DesensitizationSerializer extends JsonSerializer<String>  {
    // 序列化处理
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 脱敏成***
        gen.writeString("***");
    }
    }


脱敏后截图:

397132fbf33204875d32719527b68399_6349bee326d54b3b881d207555af3893.png

   可以看到用户的姓名都已经被处理成***了.到这里问题是解决了,但是后期再有其他的脱敏需求怎么办,比如说想对手机号进行脱敏处理,只想对前三位后两位之外的数字进行脱敏处理怎么办?重新定义一个手机号脱敏处理器?那以后需要维护的脱敏类会越来越多,显得会有所冗余,毕竟每种脱敏处理器中仅有脱敏策略不同,是否可以只专注于脱敏策略的实现,对于序列化的实现进行统一处理.基于上面的疑问就有了脱敏处理的进阶版,请往下看!


进阶版处理


自定义脱敏注解

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerializer.class)
public @interface DesensitizationAnnotation {
    Class<? extends DesensitizationStrategy> strategy();
}

自定义脱敏注解序列化处理器


public class DesensitizationSerializer extends JsonSerializer<String> implements ContextualSerializer {
    // 脱敏处理策略
    private DesensitizationStrategy desensitizationStrategy;
    public DesensitizationSerializer() {
    }
    public DesensitizationSerializer(DesensitizationStrategy desensitizationStrategy) {
        this.desensitizationStrategy = desensitizationStrategy;
    }
    // 序列化核心处理
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        int a=0;
        // 脱敏处理公共逻辑
        String desensitizationValue = desensitizationStrategy.desensitizationHandle(value);
        // 序列化处理公共方案
        gen.writeString(desensitizationValue);
    }
    // 设置自定义脱敏策略:desensitizationSerializer
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        JsonSerializer<?> desensitizationSerializer = null;
        if(null == property) desensitizationSerializer = prov.findNullValueSerializer(property);
        if(!Objects.equals(property.getType().getRawClass(), String.class))
            desensitizationSerializer = prov.findValueSerializer(property.getType(), property);
        if(Objects.equals(property.getType().getRawClass(), String.class)){
            // JsonSerializer设置自定义脱敏策略
            desensitizationSerializer = handleDesensitizationSerializer(desensitizationSerializer, property);
        }
        return desensitizationSerializer;
    }
    // 脱敏设置
    private JsonSerializer<?> handleDesensitizationSerializer(JsonSerializer<?> desensitizationSerializer, BeanProperty beanProperty) {
        // 获取脱敏注解
        DesensitizationAnnotation desensitizationJsonSerializer = beanProperty.getAnnotation(DesensitizationAnnotation.class);
        if (desensitizationJsonSerializer == null) desensitizationJsonSerializer = beanProperty.getContextAnnotation(DesensitizationAnnotation.class);
        // 设置脱敏实例,添加自定义脱敏策略
        if (desensitizationJsonSerializer != null) {
            try {
                desensitizationSerializer = new DesensitizationSerializer(desensitizationJsonSerializer.strategy().newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return desensitizationSerializer;
    }
}


实体类中添加序列化处理器


public class ShopPostInfo implements Serializable {
    private static final long serialVersionUID = -2040496864515327697L;
    // modify by txm 2022/10/4 数据脱敏处理
    // @JsonSerialize(using = DesensitizationSerializer.class)
    @DesensitizationAnnotation(strategy = FullSensitization.class)
    private String userName;
// 省略其他信息
}


全部脱敏处理策略:

public class FullSensitization implements DesensitizationStrategy{
    // 全脱敏处理
    @Override
    public String desensitizationHandle(String oldValue) {
        return "***";
    }
}


指定格式脱敏策略,这里指定只对用户姓名第一个字以外进行脱敏处理(暂时没想出更合理的脱敏场景,能理解要优化的点就行)

public class PatternDeSensitization implements DesensitizationStrategy{
    // 部分脱敏处理,首个字符处理,其余都脱敏.这里使用的hutool中的strUtil工具类,直接使用string原生的方法也可以.
    @Override
    public String desensitizationHandle(String oldValue) {
        return StrUtil.replace(oldValue,1,oldValue.length(),'*');
    }
}


测试结果:

   全部脱敏实现效果:

397132fbf33204875d32719527b68399_6349bee326d54b3b881d207555af3893.png


   部分脱敏实现效果:

81d6320b8bb98dff49ceb1a43b8a67c7_d280a42de2c344c3b3b1cf07c9cdfaf6.png

   以上是关于数据脱敏的实现方式,其中根据业务需求做了一下结构优化,如果有相同的业务需求,看完希望对你有帮助,欢迎评论区留言点赞!


相关文章
|
19天前
|
Java 程序员 容器
Java中的变量和常量:数据的‘小盒子’和‘铁盒子’有啥不一样?
在Java中,变量是一个可以随时改变的数据容器,类似于一个可以反复打开的小盒子。定义变量时需指定数据类型和名称。例如:`int age = 25;` 表示定义一个整数类型的变量 `age`,初始值为25。 常量则是不可改变的数据容器,类似于一个锁死的铁盒子,定义时使用 `final` 关键字。例如:`final int MAX_SPEED = 120;` 表示定义一个名为 `MAX_SPEED` 的常量,值为120,且不能修改。 变量和常量的主要区别在于变量的数据可以随时修改,而常量的数据一旦确定就不能改变。常量主要用于防止意外修改、提高代码可读性和便于维护。
|
2月前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
42 6
|
2月前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
99 3
|
20天前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
44 2
|
20天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
25 2
|
24天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
40 2
|
2月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
36 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
28天前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
61 3
|
28天前
|
小程序 前端开发 算法
|
1月前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
42 2

热门文章

最新文章