Commit f6601ab6390a9a36facec8df78cecb2ccfdf557d
1 parent
4d88cfdf
171 fix(protection): 修复HTTP接口签名 API重复请求问题
Showing
2 changed files
with
14 additions
and
8 deletions
yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/ApiSignatureAspect.java
| ... | ... | @@ -2,10 +2,12 @@ package cn.iocoder.yudao.framework.signature.core.aop; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.lang.Assert; |
| 4 | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | +import cn.hutool.core.util.BooleanUtil; | |
| 5 | 6 | import cn.hutool.core.util.ObjUtil; |
| 6 | 7 | import cn.hutool.core.util.StrUtil; |
| 7 | 8 | import cn.hutool.crypto.digest.DigestUtil; |
| 8 | 9 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 10 | +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | |
| 9 | 11 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 10 | 12 | import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature; |
| 11 | 13 | import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO; |
| ... | ... | @@ -69,13 +71,17 @@ public class ApiSignatureAspect { |
| 69 | 71 | |
| 70 | 72 | // 3. 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 ) |
| 71 | 73 | String nonce = request.getHeader(signature.nonce()); |
| 72 | - signatureRedisDAO.setNonce(appId, nonce, signature.timeout() * 2, signature.timeUnit()); | |
| 74 | + if (BooleanUtil.isFalse(signatureRedisDAO.setNonce(appId, nonce, signature.timeout() * 2, signature.timeUnit()))) { | |
| 75 | + String timestamp = request.getHeader(signature.timestamp()); | |
| 76 | + log.info("[verifySignature][appId({}) timestamp({}) nonce({}) sign({}) 存在重复请求]", appId, timestamp, nonce, clientSignature); | |
| 77 | + throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), "存在重复请求"); | |
| 78 | + } | |
| 73 | 79 | return true; |
| 74 | 80 | } |
| 75 | 81 | |
| 76 | 82 | /** |
| 77 | 83 | * 校验请求头加签参数 |
| 78 | - * | |
| 84 | + * <p> | |
| 79 | 85 | * 1. appId 是否为空 |
| 80 | 86 | * 2. timestamp 是否为空,请求是否已经超时,默认 10 分钟 |
| 81 | 87 | * 3. nonce 是否为空,随机数是否 10 位以上,是否在规定时间内已经访问过了 |
| ... | ... | @@ -118,7 +124,7 @@ public class ApiSignatureAspect { |
| 118 | 124 | |
| 119 | 125 | /** |
| 120 | 126 | * 构建签名字符串 |
| 121 | - * | |
| 127 | + * <p> | |
| 122 | 128 | * 格式为 = 请求参数 + 请求体 + 请求头 + 密钥 |
| 123 | 129 | * |
| 124 | 130 | * @param signature signature |
| ... | ... | @@ -139,7 +145,7 @@ public class ApiSignatureAspect { |
| 139 | 145 | /** |
| 140 | 146 | * 获取请求头加签参数 Map |
| 141 | 147 | * |
| 142 | - * @param request 请求 | |
| 148 | + * @param request 请求 | |
| 143 | 149 | * @param signature 签名注解 |
| 144 | 150 | * @return signature params |
| 145 | 151 | */ | ... | ... |
yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/ApiSignatureRedisDAO.java
| ... | ... | @@ -17,7 +17,7 @@ public class ApiSignatureRedisDAO { |
| 17 | 17 | |
| 18 | 18 | /** |
| 19 | 19 | * 验签随机数 |
| 20 | - * | |
| 20 | + * <p> | |
| 21 | 21 | * KEY 格式:signature_nonce:%s // 参数为 随机数 |
| 22 | 22 | * VALUE 格式:String |
| 23 | 23 | * 过期时间:不固定 |
| ... | ... | @@ -26,7 +26,7 @@ public class ApiSignatureRedisDAO { |
| 26 | 26 | |
| 27 | 27 | /** |
| 28 | 28 | * 签名密钥 |
| 29 | - * | |
| 29 | + * <p> | |
| 30 | 30 | * HASH 结构 |
| 31 | 31 | * KEY 格式:%s // 参数为 appid |
| 32 | 32 | * VALUE 格式:String |
| ... | ... | @@ -40,8 +40,8 @@ public class ApiSignatureRedisDAO { |
| 40 | 40 | return stringRedisTemplate.opsForValue().get(formatNonceKey(appId, nonce)); |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | - public void setNonce(String appId, String nonce, int time, TimeUnit timeUnit) { | |
| 44 | - stringRedisTemplate.opsForValue().set(formatNonceKey(appId, nonce), "", time, timeUnit); | |
| 43 | + public Boolean setNonce(String appId, String nonce, int time, TimeUnit timeUnit) { | |
| 44 | + return stringRedisTemplate.opsForValue().setIfAbsent(formatNonceKey(appId, nonce), "", time, timeUnit); | |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | private static String formatNonceKey(String appId, String nonce) { | ... | ... |