不建议在运行期用动态代理“黑客式”替换敏感越界数据,因其破坏数据完整性、干扰框架契约且越界判定模糊;应选择Controller预处理、DTO校验或TypeHandler等语义明确、可审计的干预方式。

不建议在运行期用动态代理“黑客式”替换敏感越界数据。这不是技术难点问题,而是架构与安全原则的冲突。
为什么“黑客式替换”不可取
所谓“黑客式替换”,通常指绕过业务逻辑、在反射或代理层强行篡改变量值(如把超长身份证号截断、把负数金额设为0、把非法邮箱替换成默认值)。这类操作看似快捷,实则埋下三类隐患:
- 破坏数据完整性:前端传入-9999的金额,代理层静默改成0,业务校验和风控系统完全失察,后续对账或审计无法追溯原始意图
- 干扰框架契约:Spring MVC 的 @Valid、Hibernate Validator 等依赖原始参数做约束判断;代理层提前修改后,校验器看到的是“已修复”值,导致规则失效
- 越界判定本身模糊:“越界”需结合上下文——手机号11位是常规,但国际号码可能含+86前缀;密码长度限制可能随策略动态调整,硬编码在代理逻辑里极易过时
真正可控的运行期干预点
若确需在运行期拦截并处理异常数据,应选择语义明确、职责清晰、可审计的介入位置:
-
Controller 层参数预处理:用
@InitBinder注册自定义 PropertyEditor 或 Converter,仅对特定字段(如idCard)做格式归一化,不掩盖原始值,保留BindingResult可查 -
DTO 构造阶段校验与规约:在 DTO 的构造方法或
@PostConstruct中主动校验字段范围,抛出带语义的IllegalArgumentException,由全局异常处理器统一响应 - MyBatis TypeHandler:对数据库字段做读写转换,例如将存储的加密手机号,在查询时自动解密并按规则脱敏(如 138****1234),写入时按策略加密,全程不污染业务对象
如果坚持用动态代理,必须守住的底线
仅限极小范围、无框架耦合、生命周期可控的场景,例如内部配置加载器:
-
代理目标只能是接口,如
Map.class或自定义SensitiveConfig接口,绝不能代理HashMap或ArrayList等具体实现类 -
只重写明确行为的方法,如
get()和put(),禁止拦截size()、keySet()等可能被框架高频调用的方法 -
所有替换逻辑必须可配置、可关闭、带日志,例如通过
System.getProperty("sensitive.replace.enable", "false")控制开关,并记录每次替换的 key、原始值、替换后值、触发堆栈
本质上,敏感数据治理不是靠“替换”来兜底,而是靠分层校验、明确契约和可观测性来保障。越界数据应当暴露出来,而不是被悄悄抹平。

















