SpringBoot整合FastJson2 数据脱敏:接口、日志与失败降级
问题现场: 手机号打星号只是数据脱敏最直观的例子。生产系统还要面对身份证、银行卡、地址、Token、嵌套对象以及日志参数,不同输出通道可能走完全不同的序列化链。
如果只在 DTO getter 中处理,会污染业务数据;只配置 JSON 过滤器,日志又可能继续输出原值。脱敏需要作用于输出边界,并分别覆盖接口与日志。
MetaLite 使用 FastJson2 字段过滤器处理接口序列化,同时让日志链拥有独立脱敏入口。本文先建立多通道威胁模型,再结合 FieldDesensitizeFilter 和 BaseAspectLogger 验证覆盖范围。
一、工具层解决可复用的字符规则
DesensitizeTypeEnum 内置手机号、身份证、银行卡和中文姓名规则:
PHONE(3, 4)
ID_CARD(6, 4)
BANK_CARD(6, 4)
CN_NAME(1, 2)
Desensitizer 还支持自定义保留前后位数,并能处理 List、Set 和数组。
这层适合业务主动生成脱敏副本,例如导出预览或客服页面。它不应直接修改持久化实体,否则原始数据可能被不可逆覆盖。
二、字段级序列化脱敏怎样工作
FastJson.obj2Json 可以同时接收忽略规则和脱敏规则。FieldDesensitizeFilter 在序列化每个字段时按名称匹配:
字段名命中规则
→ 值转为字符串
→ 使用内置类型或 before/after 规则脱敏
→ 输出替换后的值
这种方式不要求 DTO 到处调用工具方法,特别适合统一切面日志。
边界是规则按字段名称匹配。不同对象中同名字段语义不同、字段改名或嵌套结构变化,都可能导致规则失效或误处理。
三、忽略字段和脱敏字段不是一回事
IgnoreRule 可以按字段名或字段类型简称完全跳过序列化。对于密码、私钥、原始请求体等高敏感内容,“不输出”通常比“部分打星号”更安全。
建议按风险分层:
- 密码、密钥、Token:直接忽略;
- 手机号、证件号:按场景脱敏;
- 普通业务字段:按日志等级决定是否输出;
- 大对象或文件内容:按类型忽略,避免日志膨胀。
脱敏后的数据仍可能是个人信息,不能因为出现星号就降低访问控制。
四、切面日志如何复用这些规则
BaseAspectLogger 从 PrintControl 读取忽略字段名和类型,再调用 FastJson2 生成请求、响应或异常日志。
这让 API 接收、RPC、DAO、Redis、Caffeine 和任务等多类切面可以使用同一套打印规则,而不是每个 Logger 自己拼 JSON。
集中治理的价值很大:一处配置可以影响多条日志链。但影响面同样很大,规则修改后必须验证所有切面类型,避免为了排查一个问题临时打开全量敏感字段。
五、当前工具的几个容易误解的边界
Desensitizer 对以下输入会直接返回原值:
before或after小于 0;- 两者同时为 0;
- 字符串已经包含星号;
- 前保留位数大于等于字符串长度。
这些规则有助于避免重复脱敏,但也意味着错误配置可能静默不生效。尤其是“包含星号就跳过”,不能用来判断一段数据已经符合预期规则。
关键规则应有样例测试,而不是只看配置加载成功。
六、脱敏失败时日志本身也可能泄露
FastJson2 字段脱敏过滤器捕获异常后会记录对象类型、字段名、原始 value 和失败原因。
这对排查很直接,但也形成反向泄露路径:正常序列化想隐藏的值,可能在失败日志中完整出现。
更稳妥的原则是:脱敏失败只记录字段名、类型和错误摘要,不再记录原始值;必要时把受控诊断信息放入有独立权限和留存策略的审计通道。
七、接口响应脱敏不能代替日志脱敏
同一个手机号可能经过多条路径:
数据库实体
→ Service DTO
→ 接口响应
→ AOP 请求/响应日志
→ RPC 调用日志
→ 缓存对象
→ 异常上下文
只在最终响应上加星号,前面的日志和缓存仍可能保存原文。反过来,只处理日志,也不能阻止接口越权返回敏感字段。
所以脱敏必须与字段最小化、权限控制、加密存储和日志访问权限共同设计。
八、怎样验证脱敏真的生效
至少要覆盖这些测试:
- 正常手机号、证件号、银行卡和中文姓名;
- 空值、短字符串、已含星号和错误规则;
- 嵌套对象、集合、数组和同名字段;
- 请求日志、响应日志、异常日志和 RPC 日志;
- 脱敏器抛异常时是否仍暴露原始值。
一条字符串测试通过,不代表整条数据链已经安全。
九、脱敏的目标是控制传播
MetaLite 把工具规则、JSON 过滤和统一切面连接起来,为集中治理提供了基础。真正的安全目标不是“输出看起来有星号”,而是让敏感数据只在必要的环节、以必要的精度、被必要的人看到。
当团队开始按数据传播链审查,而不是按某个工具类审查,脱敏才从格式处理变成工程治理。
十、用一份固定样本做脱敏回归
准备包含手机号、身份证、银行卡、姓名、密码、Token、嵌套对象和超长集合的 DTO,让它同时经过接口序列化与 BaseAspectLogger。回归测试应保存允许公开的期望结果,而不是只断言字符串里出现了星号。
尤其要测试三类失败:字段值为 null 或类型不匹配、脱敏规则自身抛异常、JSON 序列化失败。日志治理代码不能因为失败把原始对象直接回退打印,否则最需要保护的数据恰好会在异常路径泄露。
接口 DTO 的 FieldDesensitizeFilter 与日志的 PrintControl 应分别验收,因为“对客户端隐藏”与“对运维日志隐藏”是两个传播边界。
十一、源码阅读要区分序列化链和日志链
接口序列化从 backend-application/.../FastJson.java 中的 FieldDesensitizeFilter 入手,关注字段值怎样按规则替换;日志链则从 BaseAspectLogger 入手,关注参数与返回值何时序列化、PrintControl 怎样限制字段和长度。
两条链即使复用同一种手机号规则,也不能共用同一个验收结论。接口响应可能已经打星,切面却在序列化前打印了原对象;日志安全仍然失败。
十二、脱敏规则还要验证“不可逆但可辨认”
手机号保留前三后四便于客服识别,密码和 Token 则不应该保留可利用片段。身份证、银行卡、邮箱和姓名也有不同识别需求,不能用一个通用 substring 覆盖所有类型。
测试样本应同时包含极短字符串、Unicode 姓名、空白、格式错误值和集合嵌套。期望结果要逐字段固定,避免“只要包含星号就算通过”。对于无法识别的敏感类型,默认全隐藏通常比原样返回更安全。
框架简介
MetaLite 是面向企业生产环境的新一代 Java 微服务技术底座。系列文章重点分享代码背后的设计思路、技术取舍与工程实践。
源码基线
JDK 21、Spring Boot 3.2.9、Spring Cloud 2023.0.1、Spring Cloud Alibaba 2023.0.1.3,具体组件版本以项目 backend-bom 为准。
作者简介
15 年 Spring 体系企业级开发经验,专注于 Java 微服务架构、工程治理与生产实践。
持续更新
MetaLite 系列内容将持续更新,围绕核心设计、源码链路、技术取舍与生产实践展开。欢迎关注作者,及时获取后续内容。
在线演示
演示地址: https://admin.metalite.top/
演示账号: guess
演示密码: admin@2026

169

被折叠的 条评论
为什么被折叠?



