Spring MVC推荐用RequestBodyAdvice在Controller执行前拦截请求体,完成解密与验签后交由绑定;支持JSON/表单,可通过注解、路径或白名单控制启用范围,失败时抛异常并由@ControllerAdvice统一返回标准错误响应。

Spring MVC 处理请求参数的解密与验签,核心思路是**在 Controller 方法执行前拦截原始请求体,完成解密、验签逻辑,并将可信明文交由后续流程自动绑定**。推荐使用 RequestBodyAdvice,它专为此类预处理设计,比拦截器(Interceptor)更精准、比手动写在每个接口里更优雅。
用 RequestBodyAdvice 实现解密+验签
RequestBodyAdvice 是 Spring 提供的请求体增强接口,有三个关键阶段可介入:
-
supports():判断当前接口是否需要处理(例如跳过带
@IgnoreSecurity注解的方法,或只处理特定 ContentType) -
beforeBodyRead():读取原始请求流,解密并校验签名,构造新的
HttpInputMessage返回(这是解密主战场) - afterBodyRead():明文对象已生成,可做字段级校验(如检查 timestamp 是否超时),但不能改类型
示例关键逻辑(伪代码):
- 从 inputMessage 获取原始字节 → 解析 JSON 得到{"timestamp":"1724184000000","data":"xxx","sign":"yyy"}- 用密钥和算法(如 SHA-256)重新计算 sign:
SHA256("data=xxx×tamp=1724184000000"),比对失败则抛异常- 对
data 字段 AES 解密,得到真实业务 JSON 字符串- 将解密后的字符串包装成新的 InputStream,替换原 inputMessage 的 body
兼容不同请求格式(JSON / 表单)
第三方可能用 application/json 或 application/x-www-form-urlencoded 提交。RequestBodyAdvice 默认只处理 JSON 类型(@RequestBody 场景),要支持表单需额外适配:
- 在
supports()中判断converterType是否为FormHttpMessageConverter或检查inputMessage.getHeaders().getContentType() - 对表单类型,先用
IOUtils.toString(inputMessage.getBody(), "UTF-8")解析为timestamp=...&data=...&sign=...,再按规则提取字段 - 解密后,若目标 Controller 参数是 POJO,需确保解密结果结构与 POJO 字段名匹配(如解密出
{"userId":"123","amount":100})
灵活控制哪些接口启用安全机制
不是所有接口都需要加解密。可通过以下方式分级控制:
-
注解驱动:定义
@RequireSecurity自定义注解,加在 Controller 方法上;supports()中通过parameter.getMethod().isAnnotationPresent(RequireSecurity.class)判断 -
路径匹配:在
supports()中检查parameter.getMethod().getDeclaringClass().getName()或 URL 路径前缀(需结合 HandlerMethod 获取) - 白名单配置:将需保护的接口路径写入配置文件(如 yml),在 Advice 中读取比对
验签失败的统一响应
验签或解密失败属于非法请求,不应进入业务层。最佳实践是在 beforeBodyRead() 中直接抛出异常,再配合 @ControllerAdvice 全局捕获:
- 自定义异常如
SecurityException,携带错误码(如 40101)和提示("签名无效") - 全局异常处理器返回标准 JSON 格式:
{"code":40101,"msg":"签名无效","data":null},状态码设为 401 或 400 - 避免在 Advice 内直接写 response,保持职责清晰
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











