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

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


相关文章
|
1月前
|
前端开发 JavaScript Java
java常用数据判空、比较和类型转换
本文介绍了Java开发中常见的数据处理技巧,包括数据判空、数据比较和类型转换。详细讲解了字符串、Integer、对象、List、Map、Set及数组的判空方法,推荐使用工具类如StringUtils、Objects等。同时,讨论了基本数据类型与引用数据类型的比较方法,以及自动类型转换和强制类型转换的规则。最后,提供了数值类型与字符串互相转换的具体示例。
|
3月前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
59 6
|
3月前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
131 3
|
5天前
|
存储 分布式计算 Hadoop
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
30 7
|
19天前
|
存储 Java BI
java怎么统计每个项目下的每个类别的数据
通过本文,我们详细介绍了如何在Java中统计每个项目下的每个类别的数据,包括数据模型设计、数据存储和统计方法。通过定义 `Category`和 `Project`类,并使用 `ProjectManager`类进行管理,可以轻松实现项目和类别的数据统计。希望本文能够帮助您理解和实现类似的统计需求。
68 17
|
2月前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
40 3
|
2月前
|
Java 程序员 容器
Java中的变量和常量:数据的‘小盒子’和‘铁盒子’有啥不一样?
在Java中,变量是一个可以随时改变的数据容器,类似于一个可以反复打开的小盒子。定义变量时需指定数据类型和名称。例如:`int age = 25;` 表示定义一个整数类型的变量 `age`,初始值为25。 常量则是不可改变的数据容器,类似于一个锁死的铁盒子,定义时使用 `final` 关键字。例如:`final int MAX_SPEED = 120;` 表示定义一个名为 `MAX_SPEED` 的常量,值为120,且不能修改。 变量和常量的主要区别在于变量的数据可以随时修改,而常量的数据一旦确定就不能改变。常量主要用于防止意外修改、提高代码可读性和便于维护。
|
2月前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
216 2
|
2月前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
46 2
|
2月前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
88 2

热门文章

最新文章