java日志敏感数据脱敏核心是禁止明文输出,通过logback自定义converter、mdc字段级脱敏、aop+@sensitive注解三种方式统一拦截处理,避免手动拼接,支持配置开关与线程安全。

Java 中敏感数据脱敏在日志记录中,核心是**不让明文敏感信息(如手机号、身份证号、银行卡号、邮箱等)直接输出到日志文件或控制台**。实现方式不是修改业务代码到处加字符串处理,而是通过日志框架的扩展能力,在日志落盘前统一拦截并替换敏感字段。
使用 Logback 的 PatternLayout + 自定义转换器
Logback 支持自定义转换器(Converter),可在日志格式化阶段对日志内容做动态脱敏。
- 编写一个继承
ClassicConverter的类,比如DesensitizeConverter,重写convert()方法,识别并脱敏常见敏感格式(如 11 位手机号、18 位身份证) - 在
logback.xml中声明该转换器: - 在
pattern中使用:
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %des{%msg}%n
这样所有%msg都会经过脱敏逻辑再输出
借助 MDC 实现字段级精准脱敏
当敏感数据来自特定参数(如用户登录时的 phone、idCard),可结合 MDC(Mapped Diagnostic Context)临时绑定键值对,在日志模板中按 key 脱敏,避免误伤正常文本。
- 业务代码中:
MDC.put("phone", "13812345678"); - 自定义 Layout 或 Converter 中检查 MDC 是否含指定 key,并只对这些 key 的 value 做脱敏(如保留前3后4:
138****5678) - 日志 pattern 示例:
%d %X{phone:-} %msg→ MDC 中的 phone 会先被脱敏再填入
用 AOP + 自定义注解统一拦截日志入参
对 Controller 或 Service 方法的入参自动脱敏,尤其适合 Spring Boot 项目。
- 定义注解
@Sensitive,标注在需要脱敏的参数或对象字段上 - 写一个切面(
@Aspect),在@Before或日志打印前,递归扫描参数对象,对带@Sensitive的字段执行脱敏(如调用DesensitizationUtil.maskPhone()) - 配合 SLF4J 的
logger.debug("login, req={}", req),此时req已是脱敏后的对象,toString() 或 JSON 序列化结果自然不泄露敏感信息
避免踩坑的关键细节
-
不要在日志语句里手动拼接脱敏:如
log.info("user: " + mask(phone))—— 这样既难维护,又可能因异常导致脱敏逻辑跳过 - 脱敏逻辑要可配置、可开关:开发环境可关掉脱敏便于调试,生产必须开启;建议通过配置中心或 JVM 参数控制
-
警惕 JSON 日志中的嵌套敏感字段:若用
ObjectMapper打印对象,需注册自定义序列化器(SimpleModule.addSerializer())对敏感字段类型做脱敏 - 注意线程安全:MDC 是 ThreadLocal,AOP 切面和 Converter 中避免共享可变状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











