java注解本身不实现防篡改签名校验,需结合aop或拦截器:通过自定义@signverify注解标记方法,切面提取参数、排序拼接、加盐哈希后与请求sign比对,同时校验timestamp防重放。

Java 中注解本身不能直接实现接口防篡改签名校验,它只是元数据标记。真正起作用的是配合 AOP(如 Spring AOP)或拦截器,在方法执行前自动提取参数、构造签名、验证签名合法性。
核心思路:注解 + 拦截 + 签名算法
通过自定义注解标记需要校验的接口方法,再用统一拦截机制(如 @Around 切面)读取该注解,对请求参数做标准化处理(排序、拼接、加盐、哈希),比对客户端传入的签名字段(如 sign)是否一致。
定义防篡改校验注解
创建一个运行时保留的注解,用于标记需签名校验的方法:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SignVerify {
String salt() default "your_app_secret"; // 可配置盐值
String signParam() default "sign"; // 签名字段名
boolean required() default true; // 是否强制校验
}
编写签名验证切面(Spring AOP 示例)
在切面中完成以下逻辑:
- 检查目标方法是否标注
@SignVerify - 从请求中提取所有业务参数(排除
sign、timestamp等非业务字段) - 按参数名字典序排序,拼接成
key1=value1&key2=value2格式 - 追加时间戳(可选)、盐值,再用 SHA-256 或 HMAC-SHA256 计算摘要
- 将计算结果与请求中的
sign字段进行恒定时间比对(防侧信道攻击) - 校验失败抛出异常(如
SignatureInvalidException),由全局异常处理器返回错误码
客户端签名生成示例(供对照)
客户端需按相同规则生成签名,例如:
// Java 客户端伪代码
Map<string string> params = new HashMap();
params.put("userId", "123");
params.put("amount", "100.00");
params.put("timestamp", "1717023456000");
String salt = "your_app_secret";
String sign = hmacSha256(sortAndJoin(params) + "×tamp=1717023456000", salt);</string>
服务端切面会做完全相同的拼接和哈希操作,结果不一致即拒绝请求。
注意事项与加固点
- 必须校验
timestamp防重放,建议允许前后 5 分钟窗口 - 敏感参数(如密码、token)不应参与签名,也不应被透传到签名逻辑中
- 签名字段名(
signParam)和盐值(salt)可通过配置中心动态管理 - 避免直接使用
String.equals()比对签名,改用MessageDigest.isEqual()或Arrays.equals() - GET 请求从 QueryString 提取参数,POST JSON 请求需先解析 body 并转为 Map
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










