“捕获捕获”指在方法调用前后两次拦截敏感数据:入参时捕获原始值,返回/输出前对字段脱敏;字节码增强(如bytebuddy)在类加载时动态织入逻辑,不改源码,支持dto序列化、日志打印、数据库结果封装三类场景,需区分展示侧与运行侧、避免重复脱敏,并处理泛型、继承及lombok等边界。

什么是捕获捕获与字节码增强的组合思路
“捕获捕获”不是标准术语,实际指在方法调用前后通过 AOP 或字节码插桩方式“两次捕获”——一次在入参时获取原始敏感数据,一次在返回/输出前对结果中对应字段做脱敏处理。字节码增强(如 ByteBuddy、ASM、Java Agent)则让这个过程无需修改源码:直接在类加载时动态织入脱敏逻辑。
核心实现路径:不改代码,只改字节码
关键在于识别敏感字段的使用场景,而非侵入业务逻辑。常见有三类目标:
-
DTO/VO 对象序列化前:如 Spring MVC 返回 JSON 时,自动对标注
@Sensitive的字段做掩码(如手机号 → 138****1234) -
日志打印前:拦截
logger.info("user={}", user)中的user,对其敏感字段脱敏后再格式化 -
数据库查询结果封装后:在 MyBatis 的
ResultSetHandler或 JPA 的AttributeConverter之外,用字节码增强拦截new User()或setXXX()后的实例
具体落地步骤(以 ByteBuddy + Java Agent 为例)
无需改动任何业务类,只需一个 agent jar 和少量配置:
- 定义注解
@Sensitive(field = "phone", strategy = MaskStrategy.MOBILE),标记在字段或 getter 上 - 编写 Agent:用 ByteBuddy 拦截所有含
@Sensitive字段的类的toString()、getXXX()、JSON 序列化入口(如 Jackson 的BeanSerializer.serialize()) - 在拦截逻辑中反射读取字段值,匹配注解策略,执行对应脱敏(如正则替换、固定掩码、AES 加密 ID 等)
- 启动时加 JVM 参数:
-javaagent:/path/to/sensitive-agent.jar
注意事项与边界情况
这种方案强大但需谨慎处理几类问题:
- 脱敏不能影响业务校验逻辑——比如不能对数据库查询条件中的手机号脱敏,否则查不到数据;应区分「展示侧」和「运行侧」上下文
- 避免重复脱敏:同一对象被多次序列化时,需缓存已脱敏标记,或确保脱敏逻辑幂等
- 泛型与继承场景下,字段可能来自父类或参数化类型,字节码增强时要递归扫描
getDeclaredFields()并处理桥接方法 - 某些框架(如 Lombok)生成的 getter/setter 可能无源码行号,需启用
-parameters编译参数并结合MethodDescription准确匹配











