123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- package com.smppw.analysis.infrastructure.components;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.crypto.SignUtil;
- import cn.hutool.json.JSONUtil;
- import com.smppw.analysis.infrastructure.config.AnalysisProperty;
- import com.smppw.common.pojo.ResultVo;
- import jakarta.servlet.http.HttpServletRequest;
- import jakarta.servlet.http.HttpServletResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.http.MediaType;
- import org.springframework.lang.NonNull;
- import org.springframework.web.servlet.HandlerInterceptor;
- import java.nio.charset.Charset;
- import java.time.Duration;
- import java.util.Map;
- /**
- * @author wangzaijun
- * @date 2023/8/7 15:58
- * @description api验证签名拦截器
- */
- public class ApiSignInterceptor implements HandlerInterceptor {
- private static final long MAX_TIMEOUT = 50000L;
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
- private final AnalysisProperty property;
- public ApiSignInterceptor(AnalysisProperty property) {
- this.property = property;
- }
- @Override
- public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
- if (logger.isInfoEnabled()) {
- logger.info(StrUtil.format("{} 接口正在被 {} 请求!", request.getRequestURI(), request.getRemoteAddr()));
- }
- if (!this.property.getEnableSign()) {
- if (logger.isDebugEnabled()) {
- logger.debug("接口不需要签名验证!");
- }
- return HandlerInterceptor.super.preHandle(request, response, handler);
- }
- String sign = request.getHeader("sign");
- if (StrUtil.isBlank(sign)) {
- this.writeFailJson(response, "sign 参数为空");
- return false;
- }
- String timestamp = request.getHeader("timestamp");
- if (StrUtil.isBlank(timestamp)) {
- this.writeFailJson(response, "timestamp 参数为空");
- return false;
- }
- String appKey = request.getParameter("appKey");
- AnalysisProperty.AppSign appSign = this.property.getAppSigns().stream()
- .filter(e -> appKey.equals(e.getAppKey())).findFirst().orElse(null);
- if (appSign == null) {
- this.writeFailJson(response, "appKey非法");
- return false;
- }
- if (!appSign.getEnabled()) {
- logger.warn(StrUtil.format("{} 应用未开启接口签名验证!", appKey));
- return HandlerInterceptor.super.preHandle(request, response, handler);
- }
- boolean flag = this.checkTimestamp(request, response, timestamp, appSign.getTimeout());
- if (!flag) {
- return false;
- }
- String appSecret = appSign.getAppSecret();
- Map<String, String[]> parameterMap = request.getParameterMap();
- parameterMap.entrySet().removeIf(next -> "appKey".equalsIgnoreCase(next.getKey()));
- String paramsSign = SignUtil.signParamsMd5(parameterMap, appSecret);
- if (!sign.equalsIgnoreCase(paramsSign)) {
- this.writeFailJson(response, "签名验证失败");
- return false;
- }
- return HandlerInterceptor.super.preHandle(request, response, handler);
- }
- private boolean checkTimestamp(HttpServletRequest request, HttpServletResponse response, String timestamp, Duration timeout) throws Exception {
- long millis = System.currentTimeMillis();
- long time = Long.parseLong(timestamp);
- long seconds = Math.min(timeout.getSeconds(), MAX_TIMEOUT);
- if (millis - time > seconds) {
- logger.error(StrUtil.format("接口有重放攻击,调用方:{}-{}"), request.getRemoteUser(), request.getRemoteAddr());
- this.writeFailJson(response, "请求失败!");
- return false;
- }
- return true;
- }
- private synchronized void writeFailJson(HttpServletResponse response, String msg) throws Exception {
- ResultVo<?> resultVo = ResultVo.fail(400, msg);
- response.setContentType(MediaType.APPLICATION_JSON_VALUE);
- response.setCharacterEncoding(Charset.defaultCharset().displayName());
- response.getWriter().write(JSONUtil.toJsonStr(resultVo));
- response.getWriter().flush();
- }
- }
|