java中推荐用jackson配合@sensitive注解实现字段脱敏:定义运行时注解标记字段,通过自定义sensitiveserializer结合contextualserializer动态识别注解并调用可插拔masker工具执行掩码,避免原生serializable的侵入式重写。

Java 中可以通过自定义注解 + ObjectOutputStream 子类或更推荐的 JSON 序列化框架(如 Jackson)实现字段脱敏,核心在于拦截序列化过程、识别注解、对标注字段执行脱敏逻辑。
定义脱敏注解 @Sensitive
声明一个运行时保留的注解,用于标记需要脱敏的字符串字段:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Sensitive {
// 可扩展策略类型,如 PHONE、ID_CARD、EMAIL 等
String value() default "DEFAULT";
}
Jackson 配合注解实现自动脱敏(推荐)
Jackson 是主流 JSON 序列化方案,支持通过 Serializer 和注解结合的方式,在序列化时动态替换值。步骤如下:
- 编写自定义序列化器
SensitiveSerializer,根据注解参数选择脱敏规则(如手机号中间4位掩码为138****1234) - 定义模块级注解处理器:继承
SimpleModule,注册SensitiveSerializer绑定到String.class,但仅对带@Sensitive的字段生效 - 使用
@JsonSerialize(using = SensitiveSerializer.class)显式标注字段 —— 或更灵活地用BeanPropertyWriter动态判断是否含@Sensitive注解(需重写SimpleBeanPropertyFilter或使用ContextualSerializer)
示例关键片段:
public class SensitiveSerializer extends JsonSerializer<string> {
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
if (value == null) {
gen.writeNull();
return;
}
// 从当前序列化上下文获取字段注解(需配合 ContextualSerializer)
Sensitive sensitive = getSensitiveAnnotation(gen);
String masked = mask(value, sensitive.value());
gen.writeString(masked);
}
}</string>
不依赖框架的原生 Serializable 脱敏(慎用)
Java 原生 Serializable 不支持注解驱动的字段级干预,但可通过以下方式间接实现:
- 在目标类中重写
writeObject(ObjectOutputStream out)方法,用反射扫描本类所有字段,检查是否含@Sensitive;若命中且为 String 类型,则写入脱敏后值,其余字段调用defaultWriteObject() - 缺点明显:破坏透明序列化契约;无法跨继承链复用;反序列化仍得重写
readObject保持一致性;且仅作用于二进制流,不适用于 JSON/XML 场景
统一脱敏工具类与策略可插拔
脱敏逻辑应与序列化解耦,建议封装为独立工具类:
- 提供
Masker.mask(String raw, String type)方法,内置常见策略(PHONE、EMAIL、NAME),支持 SPI 扩展自定义策略 - 注解
@Sensitive("PHONE")中的字符串作为策略标识,由工具类路由到对应实现 - 避免硬编码掩码规则(如
s.substring(0,3) + "****" + s.substring(7)),提升可维护性与测试性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











