利用Jackson序列化实现数据脱敏
字数 1047 2025-08-11 08:36:16

利用Jackson序列化实现数据脱敏 - 详细教学文档

1. 背景与目标

1.1 背景

在项目中处理敏感信息(如客户手机号、身份证、车牌号等)时,直接展示存在隐私泄露风险,需要进行数据脱敏处理(用脱敏符号如*替换部分信息)。

1.2 目标

  1. 利用Jackson序列化机制实现数据脱敏
  2. 降低重复开发量,提升开发效率
  3. 形成统一有效的脱敏规则
  4. 支持可扩展、可自定义的个性化脱敏需求

2. 核心实现原理

2.1 Jackson序列化机制

通过自定义JsonSerializer实现脱敏逻辑,利用Jackson的注解系统绑定脱敏处理器。

3. 详细实现步骤

3.1 自定义脱敏序列化器

public class ObjectDesensitizeSerializer extends StdSerializer<Object> implements ContextualSerializer {
    private transient Desensitization<Object> desensitization;

    protected ObjectDesensitizeSerializer() {
        super(Object.class);
    }

    @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);
        }
    }
}

关键点:

  • 继承StdSerializer并实现ContextualSerializer接口
  • createContextual方法获取字段注解信息并创建定制序列化器
  • serialize方法执行实际脱敏逻辑

3.2 脱敏器接口与工厂

3.2.1 脱敏器接口

public interface Desensitization<T> {
    T desensitize(T target);
}

3.2.2 脱敏器工厂

public class DesensitizationFactory {
    private static final Map<Class<?>, Desensitization<?>> map = new HashMap<>();

    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 默认脱敏实现

public interface DefaultDesensitization extends Desensitization<String> {}

3.3.2 手机号脱敏器

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 注解定义

3.4.1 基础脱敏注解

@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = ObjectDesensitizeSerializer.class)
public @interface Desensitize {
    Class<? extends Desensitization<?>> desensitization();
}

3.4.2 默认脱敏注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@Desensitize(desensitization = DefaultDesensitization.class)
public @interface DefaultDesensitize {}

3.4.3 手机号脱敏注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@Desensitize(desensitization = MobileNoDesensitization.class)
public @interface MobileNoDesensitize {}

3.5 脱敏符号工具类

public class Symbol {
    public static final String STAR = "*";

    public static String getSymbol(int number, String symbol) {
        return IntStream.range(0, number)
            .mapToObj(i -> symbol)
            .collect(Collectors.joining());
    }
}

4. 使用示例

4.1 实体类定义

public class User {
    @MobileNoDesensitize
    private String mobile;
    
    @DefaultDesensitize
    private String idCard;
    
    // getters and setters
}

4.2 序列化结果

{
    "mobile": "133****5678",
    "idCard": "***************1234"
}

5. 执行流程剖析

  1. 调用JsonUtil.toJsonString()开始序列化
  2. 识别属性上的脱敏注解(如@MobileNoDesensitize
  3. 调用ObjectDesensitizeSerializer#createContextual创建序列化器
  4. 调用对应的脱敏实现(如MobileNoDesensitization#desensitize
  5. 输出脱敏后的序列化结果

6. 关键设计点

6.1 Jackson元注解机制

使用@JacksonAnnotationsInside实现组合注解,使Jackson能够识别自定义注解并应用相应的序列化逻辑。

6.2 扩展性设计

  1. 通过Desensitization接口支持自定义脱敏规则
  2. 通过注解系统支持灵活配置
  3. 工厂模式管理脱敏器实例

7. 总结

本文详细介绍了利用Jackson序列化实现数据脱敏的完整方案,包括:

  1. 自定义序列化器的实现
  2. 脱敏器接口与工厂设计
  3. 常用脱敏规则实现
  4. 注解系统设计
  5. 执行流程与关键设计点

该方案具有高度可扩展性,可以方便地添加新的脱敏规则,同时保持代码的整洁和统一性。

利用Jackson序列化实现数据脱敏 - 详细教学文档 1. 背景与目标 1.1 背景 在项目中处理敏感信息(如客户手机号、身份证、车牌号等)时,直接展示存在隐私泄露风险,需要进行数据脱敏处理(用脱敏符号如* 替换部分信息)。 1.2 目标 利用Jackson序列化机制实现数据脱敏 降低重复开发量,提升开发效率 形成统一有效的脱敏规则 支持可扩展、可自定义的个性化脱敏需求 2. 核心实现原理 2.1 Jackson序列化机制 通过自定义 JsonSerializer 实现脱敏逻辑,利用Jackson的注解系统绑定脱敏处理器。 3. 详细实现步骤 3.1 自定义脱敏序列化器 关键点: 继承 StdSerializer 并实现 ContextualSerializer 接口 createContextual 方法获取字段注解信息并创建定制序列化器 serialize 方法执行实际脱敏逻辑 3.2 脱敏器接口与工厂 3.2.1 脱敏器接口 3.2.2 脱敏器工厂 3.3 常用脱敏器实现 3.3.1 默认脱敏实现 3.3.2 手机号脱敏器 3.4 注解定义 3.4.1 基础脱敏注解 3.4.2 默认脱敏注解 3.4.3 手机号脱敏注解 3.5 脱敏符号工具类 4. 使用示例 4.1 实体类定义 4.2 序列化结果 5. 执行流程剖析 调用 JsonUtil.toJsonString() 开始序列化 识别属性上的脱敏注解(如 @MobileNoDesensitize ) 调用 ObjectDesensitizeSerializer#createContextual 创建序列化器 调用对应的脱敏实现(如 MobileNoDesensitization#desensitize ) 输出脱敏后的序列化结果 6. 关键设计点 6.1 Jackson元注解机制 使用 @JacksonAnnotationsInside 实现组合注解,使Jackson能够识别自定义注解并应用相应的序列化逻辑。 6.2 扩展性设计 通过 Desensitization 接口支持自定义脱敏规则 通过注解系统支持灵活配置 工厂模式管理脱敏器实例 7. 总结 本文详细介绍了利用Jackson序列化实现数据脱敏的完整方案,包括: 自定义序列化器的实现 脱敏器接口与工厂设计 常用脱敏规则实现 注解系统设计 执行流程与关键设计点 该方案具有高度可扩展性,可以方便地添加新的脱敏规则,同时保持代码的整洁和统一性。