|
|
@@ -5,11 +5,14 @@ import cn.hutool.json.JSONUtil;
|
|
|
import com.zswl.dataservice.auth.OpenAPIContext;
|
|
|
import com.zswl.dataservice.dao.openApi.BlackListDao;
|
|
|
import com.zswl.dataservice.dao.openApi.OpenApiRequestLogDao;
|
|
|
+import com.zswl.dataservice.dao.openApi.OpenApiSignInfoDao;
|
|
|
import com.zswl.dataservice.dataConfig.OpenAPIConfig;
|
|
|
import com.zswl.dataservice.domain.openApi.OpenApiRequestLog;
|
|
|
+import com.zswl.dataservice.domain.openApi.OpenApiSignInfo;
|
|
|
import com.zswl.dataservice.service.base.RedisService;
|
|
|
import com.zswl.dataservice.service.user.OperationLogsService;
|
|
|
import com.zswl.dataservice.type.OperationLogType;
|
|
|
+import com.zswl.dataservice.utils.AesUtils;
|
|
|
import com.zswl.dataservice.utils.DateUtils;
|
|
|
import com.zswl.dataservice.utils.HttpUtils;
|
|
|
import com.zswl.dataservice.utils.mqtt.type.LogsLevel;
|
|
|
@@ -20,11 +23,15 @@ import jakarta.servlet.ServletInputStream;
|
|
|
import jakarta.servlet.ServletOutputStream;
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
+import lombok.Data;
|
|
|
import lombok.SneakyThrows;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.ObjectUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.aspectj.apache.bcel.classfile.Module;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
@@ -35,7 +42,9 @@ import org.springframework.web.util.ContentCachingResponseWrapper;
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.io.OutputStream;
|
|
|
+import java.io.PrintWriter;
|
|
|
import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
import java.util.concurrent.Executors;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
@@ -63,6 +72,9 @@ public class OpenApiVerifyService {
|
|
|
@Autowired
|
|
|
BlackListDao blackListDao;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ OpenApiSignInfoDao openApiSignInfoDao;
|
|
|
+
|
|
|
//线程池
|
|
|
ExecutorService executorService = Executors.newFixedThreadPool(SystemUtil.getCpuCoreCount() * 2);
|
|
|
|
|
|
@@ -82,16 +94,125 @@ public class OpenApiVerifyService {
|
|
|
* @return
|
|
|
*/
|
|
|
@SneakyThrows
|
|
|
- public boolean verify(HttpServletRequest request, HttpServletResponse response, Object object) {
|
|
|
+ public boolean verifyOpenAPI(HttpServletRequest request, HttpServletResponse response, Object object) {
|
|
|
log.info("---------------------openAPI验证----------------------");
|
|
|
OpenAPIContext.setTime(System.currentTimeMillis());
|
|
|
if (request instanceof ContentCachingRequestWrapper) {
|
|
|
ContentCachingRequestWrapper contentCachingRequestWrapper = (ContentCachingRequestWrapper) request;
|
|
|
+ ContentCachingResponseWrapper responseWrapper = (ContentCachingResponseWrapper) response;
|
|
|
String requestStr = contentCachingRequestWrapper.getContentAsString();
|
|
|
- log.info("body {}", requestStr);
|
|
|
+
|
|
|
+ String msg = "认证错误";
|
|
|
+ int code = 403;
|
|
|
+ boolean isSuccess = false;
|
|
|
+ if (contentCachingRequestWrapper.getContentLength() > OpenAPIConfig.maxLen) {
|
|
|
+ setResponse(request, responseWrapper, "请求内容过大", 403, false);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ log.info("请求数据requestStr: {}", requestStr);
|
|
|
+
|
|
|
String authorization = request.getHeader("authorization");
|
|
|
+ log.info("authorization数据 {}", authorization);
|
|
|
+ if (StringUtils.isNotEmpty(authorization)) {
|
|
|
+ if (authorization.length() > OpenAPIConfig.maxLen) {
|
|
|
+ setResponse(request, responseWrapper, "请求内容过大", 403, false);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ authorization = authorization.replaceAll(" ", "");
|
|
|
+ if (authorization.startsWith(OpenAPIConfig.OPENBODYSIG)) {
|
|
|
+ authorization = authorization.replace(OpenAPIConfig.OPENBODYSIG, "");
|
|
|
+ HashMap<String, String> map = new HashMap<>();
|
|
|
+ String[] arr = authorization.split(",");
|
|
|
+ isSuccess = true;
|
|
|
+
|
|
|
+ if (arr.length > 0) {
|
|
|
+ for (String s : arr) {
|
|
|
+ for (String key : OpenAPIConfig.authKeys) {
|
|
|
+ if (s.startsWith(key)) {
|
|
|
+ String val = s.replace(key + "=", "");
|
|
|
+ val = val.replace("\"", "");
|
|
|
+ map.put(key, val);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ if (isSuccess) {
|
|
|
+ OpenApiSignInfo signInfo = null;
|
|
|
+ if (!map.containsKey("AppId")) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "没有AppId信息";
|
|
|
+ }
|
|
|
+ String appId = map.get("AppId");
|
|
|
+ signInfo = openApiSignInfoDao.findTopByAppId(appId);
|
|
|
+ if (ObjectUtils.isEmpty(signInfo)) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "AppId错误";
|
|
|
+ }
|
|
|
+ if (isSuccess && !map.containsKey("Timestamp")) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "没有Timestamp信息";
|
|
|
+ }
|
|
|
+ String timestamp = map.get("Timestamp");
|
|
|
+ if (StringUtils.isEmpty(timestamp) || timestamp.length() != 14) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "Timestamp格式错误";
|
|
|
+ }
|
|
|
|
|
|
+ if (isSuccess){
|
|
|
+ Long time = DateUtils.timeToLong(timestamp, DateUtils.unionAuth);
|
|
|
+ if (time == null || Math.abs(time - System.currentTimeMillis()) > OpenAPIConfig.timeBetween) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "Timestamp不符合要求";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isSuccess && !map.containsKey("Nonce")) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "没有Nonce信息";
|
|
|
+ }
|
|
|
+ String nonce = map.get("Nonce");
|
|
|
+ if (isSuccess && (StringUtils.isEmpty(nonce) || nonce.length() > 50)) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "Nonce为空或长度不符合要求";
|
|
|
+ }
|
|
|
+ if (isSuccess && !map.containsKey("Signature")) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "没有Signature信息";
|
|
|
+ }
|
|
|
+ String signature = map.get("Signature");
|
|
|
+ if (isSuccess && (StringUtils.isEmpty(signature) || signature.length() > 200)) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "Signature为空或长度不符合要求";
|
|
|
+ }
|
|
|
+
|
|
|
+ if(isSuccess) {
|
|
|
+ String sign = AesUtils.signData(requestStr);
|
|
|
+ log.info("数据sign {}", sign);
|
|
|
+ String appKey = signInfo.getAppKey();
|
|
|
+ String c = String.format("%s%s%s%s", appId, timestamp, nonce, sign);
|
|
|
+ String tempSignature = AesUtils.signMacSHA256(c, appKey);
|
|
|
+ log.info("系统tempSignature {}", tempSignature);
|
|
|
+ log.info("传入signature {}", signature);
|
|
|
+
|
|
|
+ if (!tempSignature.equals(signature)) {
|
|
|
+ isSuccess = false;
|
|
|
+ msg = "Signature认证错误";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ msg = "报文头没有OPEN-BODY-SIG标记";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ msg = "报文头authorization为空";
|
|
|
+ }
|
|
|
+ if (!isSuccess) {
|
|
|
+ // 验证不成功
|
|
|
+ setResponse(request, responseWrapper, msg, code, true);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
@@ -105,8 +226,48 @@ public class OpenApiVerifyService {
|
|
|
* @param modelAndView
|
|
|
*/
|
|
|
@SneakyThrows
|
|
|
- public void saveLog(HttpServletRequest request, HttpServletResponse response,
|
|
|
- Object handler, ModelAndView modelAndView) {
|
|
|
+ public void saveOpenAPILog(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
|
|
|
+ ResultContent resultContent = null;
|
|
|
+ if (response instanceof ContentCachingResponseWrapper) {
|
|
|
+ ContentCachingResponseWrapper responseWrapper = (ContentCachingResponseWrapper) response;
|
|
|
+ byte[] bytes = responseWrapper.getContentAsByteArray();
|
|
|
+ resultContent = HttpUtils.toBean(new String(bytes), ResultContent.class);
|
|
|
+ responseWrapper.copyBodyToResponse();
|
|
|
+ }
|
|
|
+ saveLog(request, resultContent);
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isInBlackList(HttpServletRequest request) {
|
|
|
+ String ip = IPUtil.getRemoteIp(request);
|
|
|
+ if (blackListDao.existsByIp(ip)) {
|
|
|
+ ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
+ RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享
|
|
|
+ executorService.execute(() -> {
|
|
|
+ operationLogsService.addLogs(String.format("黑名单地址访问: %s", ip), LogsLevel.High, OperationLogType.Black, null);
|
|
|
+ });
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @SneakyThrows
|
|
|
+ private void setResponse(HttpServletRequest request, ContentCachingResponseWrapper responseWrapper, String msg, int code, boolean isSaveLog) {
|
|
|
+ ResultContent resultContent = ResultContent.buildFail(msg, code);
|
|
|
+ responseWrapper.setCharacterEncoding("UTF-8");
|
|
|
+ responseWrapper.setHeader("Content-Type", "application/json");
|
|
|
+ responseWrapper.setStatus(HttpStatus.PAYMENT_REQUIRED.value());
|
|
|
+ PrintWriter printWriter = responseWrapper.getWriter();
|
|
|
+ printWriter.write(JSONUtil.toJsonStr(resultContent));
|
|
|
+ printWriter.flush();
|
|
|
+ printWriter.close();
|
|
|
+ responseWrapper.copyBodyToResponse();
|
|
|
+ if (isSaveLog) {
|
|
|
+ saveLog(request, resultContent);
|
|
|
+ }
|
|
|
+ resultContent = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveLog(HttpServletRequest request, ResultContent resultContent) {
|
|
|
OpenApiRequestLog openApiRequestLog = new OpenApiRequestLog();
|
|
|
JSONObject param = HttpUtils.getRequestObj(request);
|
|
|
if (param != null) {
|
|
|
@@ -129,30 +290,11 @@ public class OpenApiVerifyService {
|
|
|
}
|
|
|
openApiRequestLog.setAuthorization(request.getHeader("authorization"));
|
|
|
openApiRequestLog.setTTL(new Date(System.currentTimeMillis() + OpenAPIConfig.logTTL));
|
|
|
- if (response instanceof ContentCachingResponseWrapper) {
|
|
|
- ContentCachingResponseWrapper responseWrapper = (ContentCachingResponseWrapper) response;
|
|
|
- byte[] bytes = responseWrapper.getContentAsByteArray();
|
|
|
- ResultContent resultContent = HttpUtils.toBean(new String(bytes), ResultContent.class);
|
|
|
- if (resultContent != null) {
|
|
|
- openApiRequestLog.setIsSuccess(resultContent.isSuccess());
|
|
|
- openApiRequestLog.setErrorMsg(resultContent.getMsg());
|
|
|
- }
|
|
|
- openApiRequestLog.setResponseBody(resultContent);
|
|
|
- responseWrapper.copyBodyToResponse();
|
|
|
+ if (resultContent != null) {
|
|
|
+ openApiRequestLog.setIsSuccess(resultContent.isSuccess());
|
|
|
+ openApiRequestLog.setErrorMsg(resultContent.getMsg());
|
|
|
}
|
|
|
+ openApiRequestLog.setResponseBody(resultContent);
|
|
|
openApiRequestLogDao.save(openApiRequestLog);
|
|
|
}
|
|
|
-
|
|
|
- public boolean isInBlackList(HttpServletRequest request) {
|
|
|
- String ip = IPUtil.getRemoteIp(request);
|
|
|
- if (blackListDao.existsByIp(ip)) {
|
|
|
- ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
- RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享
|
|
|
- executorService.execute(() -> {
|
|
|
- operationLogsService.addLogs(String.format("黑名单地址访问: %s", ip), LogsLevel.High, OperationLogType.Black, null);
|
|
|
- });
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
}
|