签名失败需在controller前用拦截器或aop统一校验,抛出自定义signatureinvalidexception,由@restcontrolleradvice捕获并返回401/403;禁用controller内校验与filter,确保安全逻辑前置且与参数校验分离。

签名失败不属于 Spring 默认校验范畴,不能靠 @Valid 或 MethodArgumentNotValidException 拦截。它属于接口级安全校验,需在请求进入 Controller 之前完成,推荐用 拦截器(HandlerInterceptor) 或 AOP 切面 统一处理,并抛出自定义异常交由全局异常处理器兜底响应。
签名校验应放在拦截器中做
签名验证本质是请求头/参数完整性与合法性检查(如 timestamp、nonce、sign),必须在参数绑定和业务执行前完成:
- 拦截器的
preHandle方法可直接获取HttpServletRequest,读取 Header、Query、Body(注意 Body 只能读一次,需用ContentCachingRequestWrapper包装) - 校验逻辑包括:时间戳是否超时、nonce 是否重复、签名算法(如 HMAC-SHA256)是否匹配
- 校验失败时,不放行请求,直接抛出
SignatureInvalidException(自定义运行时异常)
定义签名异常并统一拦截
创建继承 RuntimeException 的异常类,便于全局识别和分类处理:
public class SignatureInvalidException extends RuntimeException {
public SignatureInvalidException(String msg) {
super(msg);
}
}
在 @RestControllerAdvice 中专门捕获该异常:
- HTTP 状态码设为
401 Unauthorized(未认证)或403 Forbidden(拒绝访问),语义更准确 - 响应体结构与其它异常一致,如
Result.error(401, "签名无效") - 可选:记录 traceId、请求路径、客户端 IP,便于安全审计
避免在 Controller 层做签名校验
把签名逻辑写进每个接口方法里,会导致:
- 重复代码多,易遗漏,难维护
- 无法保证执行顺序(可能在参数校验之后才校验签名)
- 违反单一职责,业务方法混入安全逻辑
也不建议用 Filter —— 它比 DispatcherServlet 更早,拿不到 Spring 的上下文(如 Locale、HandlerMapping),且对文件上传、流式响应等场景兼容性差。
补充:签名异常要和参数异常区分清楚
前端需要明确知道错误类型:
-
400 Bad Request→ 字段缺失、格式错误(走MethodArgumentNotValidException) -
401/403→ 签名无效、token 过期、权限不足(走SignatureInvalidException或AuthenticationException) -
500 Internal Server Error→ 兜底异常,不应暴露堆栈
这样前端才能精准提示用户“请检查签名参数”而非笼统提示“请求失败”。











