文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java怎么用Jackson序列化实现数据脱敏

2023-07-05 19:34

关注

这篇“Java怎么用Jackson序列化实现数据脱敏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java怎么用Jackson序列化实现数据脱敏”文章吧。

1.背景

在项目中有些敏感信息不能直接展示,比如客户手机号、身份证、车牌号等信息,展示时均需要进行数据脱敏,防止泄露客户隐私。脱敏即是对数据的部分信息用脱敏符号(*)处理。

2.目标

3.主要实现

3.1基于Jackson的自定义脱敏序列化实现

StdSerializer:所有标准序列化程序所使用的基类,这个是编写自定义序列化程序所推荐使用的基类。

ContextualSerializer: 是Jackson 提供的另一个序列化相关的接口,它的作用是通过字段已知的上下文信息定制JsonSerializer。

package com.jd.ccmp.ctm.constraints.serializer;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.databind.BeanProperty;import com.fasterxml.jackson.databind.JsonSerializer;import com.fasterxml.jackson.databind.SerializerProvider;import com.fasterxml.jackson.databind.ser.ContextualSerializer;import com.fasterxml.jackson.databind.ser.std.StdSerializer;import com.jd.ccmp.ctm.constraints.Symbol;import com.jd.ccmp.ctm.constraints.annotation.Desensitize;import com.jd.ccmp.ctm.constraints.desensitization.Desensitization;import com.jd.ccmp.ctm.constraints.desensitization.DesensitizationFactory;import com.jd.ccmp.ctm.constraints.desensitization.DefaultDesensitization;import java.io.IOException;public class ObjectDesensitizeSerializer extends StdSerializer<Object> implements ContextualSerializer {    private static final long serialVersionUID = -7868746622368564541L;    private transient Desensitization<Object> desensitization;    protected ObjectDesensitizeSerializer() {        super(Object.class);    }    public Desensitization<Object> getDesensitization() {        return desensitization;    }    public void setDesensitization(Desensitization<Object> desensitization) {        this.desensitization = desensitization;    }    @Override    public JsonSerializer<Object> createContextual(SerializerProvider prov, BeanProperty property) {//获取属性注解        Desensitize annotation = property.getAnnotation(Desensitize.class);        return createContextual(annotation.desensitization());    }    @SuppressWarnings("unchecked")    public JsonSerializer<Object> createContextual(Class<? extends Desensitization<?>> clazz) {        ObjectDesensitizeSerializer serializer = new ObjectDesensitizeSerializer();        if (clazz != DefaultDesensitization.class) {            serializer.setDesensitization((Desensitization<Object>) DesensitizationFactory.getDesensitization(clazz));        }        return serializer;    }    @Override    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {        Desensitization<Object> objectDesensitization = getDesensitization();        if (objectDesensitization != null) {            try {                gen.writeObject(objectDesensitization.desensitize(value));            } catch (Exception e) {                gen.writeObject(value);            }        } else if (value instanceof String) {            gen.writeString(Symbol.getSymbol(((String) value).length(), Symbol.STAR));        } else {            gen.writeObject(value);        }

注:createContextual可以获得字段的类型以及注解。当字段拥有自定义注解时,取出注解中的值创建定制的序列化方式,这样在serialize方法中便可以得到这个值了。createContextual方法只会在第一次序列化字段时调用(因为字段的上下文信息在运行期不会改变),所以无需关心性能问题。

3.2定义脱敏接口、以及工厂实现

3.2.1脱敏器接口定义

package com.jd.ccmp.ctm.constraints.desensitization;public interface Desensitization<T> {        T desensitize(T target);}

3.2.2脱敏器工厂实现

package com.jd.ccmp.ctm.constraints.desensitization;import java.util.HashMap;import java.util.Map;public class DesensitizationFactory {    private DesensitizationFactory() {    }    private static final Map<Class<?>, Desensitization<?>> map = new HashMap<>();    @SuppressWarnings("all")    public static Desensitization<?> getDesensitization(Class<?> clazz) {        if (clazz.isInterface()) {            throw new UnsupportedOperationException("desensitization is interface, what is expected is an implementation class !");        }        return map.computeIfAbsent(clazz, key -> {            try {                return (Desensitization<?>) clazz.newInstance();            } catch (InstantiationException | IllegalAccessException e) {                throw new UnsupportedOperationException(e.getMessage(), e);            }        });

3.3常用的脱敏器实现

3.3.1默认脱敏实现

可基于默认实现,扩展实现个性化场景

package com.jd.ccmp.ctm.constraints.desensitization;public interface DefaultDesensitization extends Desensitization<String> {}

3.3.2手机号脱敏器

实现对手机号中间4位号码脱敏

package com.jd.ccmp.ctm.constraints.desensitization;import com.jd.ccmp.ctm.constraints.Symbol;import java.util.regex.Matcher;import java.util.regex.Pattern;public class MobileNoDesensitization implements DefaultDesensitization {        private static final Pattern DEFAULT_PATTERN = Pattern.compile("(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}");    @Override    public String desensitize(String target) {        Matcher matcher = DEFAULT_PATTERN.matcher(target);        while (matcher.find()) {            String group = matcher.group();            target = target.replace(group, group.substring(0, 3) + Symbol.getSymbol(4, Symbol.STAR) + group.substring(7, 11));        }        return target;

3.4注解定义

通过@JacksonAnnotationsInside实现自定义注解,提高易用性

package com.jd.ccmp.ctm.constraints.annotation;import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;import com.fasterxml.jackson.databind.annotation.JsonSerialize;import com.jd.ccmp.ctm.constraints.desensitization.Desensitization;import com.jd.ccmp.ctm.constraints.serializer.ObjectDesensitizeSerializer;import java.lang.annotation.*;@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@JsonSerialize(using = ObjectDesensitizeSerializer.class)@Documentedpublic @interface Desensitize {        @SuppressWarnings("all")    Class<? extends Desensitization<?>> desensitization();

3.4.1默认脱敏注解

package com.jd.ccmp.ctm.constraints.annotation;import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;import com.jd.ccmp.ctm.constraints.desensitization.DefaultDesensitization;import java.lang.annotation.*;@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@Desensitize(desensitization = DefaultDesensitization.class)@Documentedpublic @interface DefaultDesensitize {

3.4.2手机号脱敏注解

package com.jd.ccmp.ctm.constraints.annotation;import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;import com.jd.ccmp.ctm.constraints.desensitization.MobileNoDesensitization;import java.lang.annotation.*;@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@Desensitize(desensitization = MobileNoDesensitization.class)@Documentedpublic @interface MobileNoDesensitize {}

3.5定义脱敏符号

支持指定脱敏符号,例如* 或是 ^_^

package com.jd.ccmp.ctm.constraints;import java.util.stream.Collectors;import java.util.stream.IntStream;public class Symbol {        public static final String STAR = "*";    private Symbol() {}        public static String getSymbol(int number, String symbol) {        return IntStream.range(0, number).mapToObj(i -> symbol).collect(Collectors.joining());    }

4.使用样例&执行流程剖析

Java怎么用Jackson序列化实现数据脱敏

程序类图

Java怎么用Jackson序列化实现数据脱敏

**执行流程剖析**

 1.调用JsonUtil.toJsonString()开始执行序列化

 2.识别属性mobile上的注解@MobileNoDesensitize(上文3.4.2)

 3.调用ObjectDesensitizeSerializer#createContextual(上文3.1 & 3.2),返回JsonSerializer

 4.调用手机号脱敏实现MobileNoDesensitization#desensitize(上文3.3.2)

 5.输出脱敏后的序列化结果,{"mobile":"133****5678"}

不难发现核心执行流程是第3步,但是@MobileNoDesensitize与ObjectDesensitizeSerializer又是如何联系起来的呢?

//1.提到元注解这个词,大家会想到@Target、@Retention、@Documented、@Inherited//2.Jackson也以同样的思路设计了@JacksonAnnotationsInside@Target({ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationpublic @interface JacksonAnnotationsInside{}

正是通过”combo-annotations”(组合注解、捆绑注解)的机制,实现了指示Jackson应该使用其拥有的元注释,而不是使用目标注释,从而实现了自定义脱敏实现设计目标。

以上就是关于“Java怎么用Jackson序列化实现数据脱敏”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯