package jnpf.encrypt; import cn.hutool.core.net.url.UrlQuery; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jnpf.annotation.EncryptApi; import jnpf.constant.GlobalConst; import jnpf.constant.MsgCode; import jnpf.exception.EncryptFailException; import jnpf.util.DesUtil; import jnpf.util.StringUtil; import jnpf.wrapper.MyRequestWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.AsyncHandlerInterceptor; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.*; /** * 接口传输加密 * 支持请求类型: * application/json * application/x-www-form-urlencoded */ @Slf4j public class EncryptRestInterceptor implements AsyncHandlerInterceptor { private static final String ENCRYPT_KEY = "encryptData"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { try { if (handler instanceof HandlerMethod && request instanceof MyRequestWrapper) { HandlerMethod method = (HandlerMethod) handler; EncryptApi methodAnnotation = method.getMethodAnnotation(EncryptApi.class); if (methodAnnotation != null && methodAnnotation.encryptRequest()) { MyRequestWrapper myRequest = (MyRequestWrapper) request; // 需要对数据进行加密解密 // application/json // application/x-www-form-urlencoded String contentType = request.getContentType(); if (contentType != null) { myRequest.wrapperRequestData(); String requestBody = null; boolean canEncrypt = false; if ((StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) || "get".equalsIgnoreCase(request.getMethod())) { // 1.application/x-www-form-urlencoded 支持参数在body或者在param canEncrypt = true; requestBody = convertFormToString(request); if ("{}".equals(requestBody)) { requestBody = URLDecoder.decode(myRequest.getRequestBody()); Map uriToListToMap = new UrlQuery().parse(requestBody, GlobalConst.DEFAULT_CHARSET).getQueryMap(); requestBody = JSONObject.toJSONString(uriToListToMap); } } else if (StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_JSON_VALUE)) { // application/json 支持加密参数在body canEncrypt = true; requestBody = myRequest.getRequestBody(); } if (canEncrypt) { if (requestBody != null && !"{}".equals(requestBody)) { JSONObject jsonBody = JSON.parseObject(requestBody); JSON result = decodeApi(jsonBody); if (result != null) { myRequest.setRequestBody(result.toJSONString()); if (result instanceof JSONObject) { myRequest.addAllParameters((Map) result); } return true; } } } } throw encryptFailException(); } } } catch (EncryptFailException eex) { throw eex; } catch (Exception e) { log.error("解密失败, 异常地址:{}", request.getServletPath(), e); throw encryptFailException(); } return true; } /** * Pamams参数转JSON字符串 * * @param request * @return */ private String convertFormToString(HttpServletRequest request) { Map result = new HashMap<>(8); Enumeration parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String name = parameterNames.nextElement(); result.put(name, request.getParameter(name)); } try { return JSON.toJSONString(result); } catch (Exception e) { throw new IllegalArgumentException(e); } } /** * 请求内容解密 * * @param body * @return */ public JSON decodeApi(JSON body) { try { JSONObject jsonObject = (JSONObject) body; String content = jsonObject.getOrDefault(ENCRYPT_KEY, "").toString(); if (!StringUtil.isEmpty(content)) { content = decryptData(content); return (JSON) JSON.parse(content); } } catch (Exception e) { log.error("解密失败, 文本: {}", body, e); } return null; } /** * 文本解密 * * @param data * @return */ protected String decryptData(String data) { if (StringUtil.isEmpty(data)) { return data; } if (Objects.equals(data.charAt(0), '"') && Objects.equals(data.charAt(data.length() - 1), '"')) { data = data.substring(1, data.length() - 1); } return DesUtil.aesOrDecode(data, false, true); } private EncryptFailException encryptFailException() { throw new EncryptFailException(MsgCode.FA051.get()); } }