在 Spring Boot 中优雅地实现数据脱敏,对于保护用户隐私和应对安全合规要求都至关重要。下面我为你梳理几种常见且实用的方案。
🎯 数据脱敏常用方案对比
方案类型 | 核心思路 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
基于 Jackson 序列化器 | 通过自定义注解和 Jackson 的 JsonSerializer 在 JSON 序列化时脱敏 |
对业务代码无侵入、集中管理、性能较好 | 可能增加序列化复杂性 | 接口返回数据脱敏(最常用) |
基于 AOP | 使用 AOP 拦截控制器返回值,通过反射进行脱敏处理 | 适用范围广,可管理各种返回值 | 反射操作可能性能稍低,需注意切入点定义 | 需要对非 JSON 响应(如 XML)脱敏 |
日志脱敏 | 使用自定义的 PatternLayout 或过滤器在记录日志时脱敏 |
防止敏感信息在日志中泄漏 | 通常需依赖特定日志框架 | 日志输出中的敏感信息保护 |
数据库层面脱敏 | 在 SQL 查询时使用函数(如 INSERT ) 进行隐藏 |
减轻应用层压力 | 耦合数据库实现,不够灵活 | 特定简单的脱敏需求 |
🔧 基于 Jackson 序列化器实现(推荐)
这是目前较为流行和优雅的一种方式,其核心是在数据序列化为 JSON 时,对标记了特定注解的字段进行脱敏处理。
1. 定义脱敏策略枚举
首先定义一个枚举来描述不同的脱敏策略及其对应的处理逻辑。
import lombok.Getter;
import java.util.function.Function;
@Getter
public enum DesensitizationStrategyEnum {
// 手机号脱敏:保留前3位和后4位,例如138****1234
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
// 邮箱脱敏:保留邮箱用户名第一个字符和@符号前后部分,例如a****@example.com
EMAIL(s -> s.replaceAll("(\\w)[^@]*(@\\w+\\.\\w+)", "$1****$2")),
// 身份证号脱敏:保留前4位和后4位,例如1101****5678
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1*****$2")),
// 银行卡号脱敏:保留前4位和后3位,例如6222****123
BANK_CARD(s -> s.replaceAll("(\\d{4})\\d{8,12}(\\d{3})", "$1************$2")),
// 姓名脱敏:保留姓氏,其余用**代替,例如张**
NAME(s -> s.charAt(0) + "**");
private final Funct