diff --git a/src/main/java/cn/lihongjie/coal/common/Constants.java b/src/main/java/cn/lihongjie/coal/common/Constants.java index 343cd623..05651533 100644 --- a/src/main/java/cn/lihongjie/coal/common/Constants.java +++ b/src/main/java/cn/lihongjie/coal/common/Constants.java @@ -12,10 +12,12 @@ public class Constants { public static final String CACHE_RESOURCE_MENU_TREE = "resourceMenuTree"; public static final String HTTP_HEADER_TOKEN = "X-Token"; public static final String HTTP_HEADER_CLIENT_SIGN = "X-Client-Sign"; + public static final String HTTP_HEADER_CLIENT_RANDOM = "X-Client-Random"; public static final String HTTP_HEADER_TS = "X-TS"; public static final String RATE_LIMIT_GLOBAL_SESSION_PREFIX = "global-session-rl-"; public static final String RATE_LIMIT_GLOBAL_USER_PREFIX = "global-user-rl-"; public static final String CACHE_ADDRESS_TYPE = "addressType"; + public static final String CACHE_CLIENT_RANDOM_PREFIX = "clientRandom::"; public static String SYSCONFIG_ENABLE_CAPTCHA = "enable_captcha"; public static String SYSCONFIG_ENABLE_REQUEST_SIGN = "enable_request_sign"; public static String SYSCONFIG_SESSION_TIMEOUT = "session_timeout"; diff --git a/src/main/java/cn/lihongjie/coal/filter/SignFilter.java b/src/main/java/cn/lihongjie/coal/filter/SignFilter.java index 4c179f57..aa286032 100644 --- a/src/main/java/cn/lihongjie/coal/filter/SignFilter.java +++ b/src/main/java/cn/lihongjie/coal/filter/SignFilter.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -32,6 +33,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.*; +import java.util.concurrent.TimeUnit; import javax.crypto.Mac; @@ -40,6 +42,7 @@ import javax.crypto.Mac; @Order(10) @Slf4j public class SignFilter extends OncePerRequestFilter { + public static final int TIME_DIFF_MS = 1000 * 60 * 2; @Autowired ObjectMapper objectMapper; @Autowired SysConfigService sysConfigService; @@ -47,6 +50,9 @@ public class SignFilter extends OncePerRequestFilter { @Autowired IpQueryService ipQueryService; @Autowired LoginUserService loginUserService; + @Autowired + RedisTemplate redisTemplate; + @Override protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) @@ -80,6 +86,13 @@ public class SignFilter extends OncePerRequestFilter { new BizException(Constants.HTTP_HEADER_TS + " 请求头缺失"), response); return; } + + String random = request.getHeader(Constants.HTTP_HEADER_CLIENT_RANDOM); + if (StringUtils.isEmpty(random)) { + RequestUtils.writeResponse( + new BizException(Constants.HTTP_HEADER_CLIENT_RANDOM + " 请求头缺失"), response); + return; + } long tsi = 0; try { @@ -93,7 +106,7 @@ public class SignFilter extends OncePerRequestFilter { long current = System.currentTimeMillis(); - if (Math.abs(tsi - current) > 1000 * 60 * 2) { + if (Math.abs(tsi - current) > TIME_DIFF_MS) { RequestUtils.writeResponse( new BizException( Constants.HTTP_HEADER_TS @@ -111,6 +124,10 @@ public class SignFilter extends OncePerRequestFilter { sb.append(StringUtils.defaultString("\n")); + sb.append(StringUtils.defaultString(random)); + + sb.append(StringUtils.defaultString("\n")); + String sha256Hex = DigestUtils.sha256Hex(request.getInputStream()).toUpperCase(); sb.append(StringUtils.defaultString(sha256Hex)); @@ -132,6 +149,18 @@ public class SignFilter extends OncePerRequestFilter { new BizException(Constants.HTTP_HEADER_CLIENT_SIGN + " 请求头签名错误"), response); return; } + + String cr = redisTemplate.opsForValue().get(Constants.CACHE_CLIENT_RANDOM_PREFIX + random); + + if (StringUtils.equals(cr, "1")){ + sysLogService.saveSysLog(request, "签名模块", "重复请求", ""); + RequestUtils.writeResponse( + new BizException("请求已过期, 请刷新页面重试"), response); + return; + }else { + redisTemplate.opsForValue().set(Constants.CACHE_CLIENT_RANDOM_PREFIX + random, "1", TIME_DIFF_MS, TimeUnit.MILLISECONDS); + } + } doFilter(request, response, filterChain);