diff --git a/lesingle-edu-reading-platform-backend/src/main/java/com/lesingle/edu/common/aspect/RequestLogAspect.java b/lesingle-edu-reading-platform-backend/src/main/java/com/lesingle/edu/common/aspect/RequestLogAspect.java index 6576aab..1318319 100644 --- a/lesingle-edu-reading-platform-backend/src/main/java/com/lesingle/edu/common/aspect/RequestLogAspect.java +++ b/lesingle-edu-reading-platform-backend/src/main/java/com/lesingle/edu/common/aspect/RequestLogAspect.java @@ -1,6 +1,7 @@ package com.lesingle.edu.common.aspect; import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.lesingle.edu.common.security.SecurityUtils; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; @@ -18,13 +19,26 @@ import java.util.Objects; /** * 请求日志切面 - * 记录所有 Controller 层的请求信息 + * 记录所有 Controller 层的请求信息(敏感信息已脱敏) */ @Slf4j @Aspect @Component public class RequestLogAspect { + /** + * 敏感字段列表(不区分大小写) + */ + private static final String[] SENSITIVE_FIELDS = { + "password", "pwd", "secret", "token", "accessToken", "refreshToken", + "oldPassword", "newPassword", "confirmPassword" + }; + + /** + * 脱敏掩码 + */ + private static final String MASK = "***"; + /** * 定义切点:Controller 层所有方法 */ @@ -62,7 +76,8 @@ public class RequestLogAspect { String methodType = request.getMethod(); String className = joinPoint.getTarget().getClass().getName(); String methodName = method.getName(); - String params = JSON.toJSONString(getRequestParams(joinPoint)); + // 请求参数脱敏处理 + String params = desensitize(getRequestParams(joinPoint)); log.info("===== 请求开始 [userId={}, role={}] =====", userId, role); log.info("接口地址:{} {}", methodType, requestURI); @@ -77,7 +92,7 @@ public class RequestLogAspect { // 记录响应结果 log.info("响应时间:{}ms", duration); - log.info("响应结果:{}", JSON.toJSONString(result)); + log.info("响应结果:{}", desensitize(result)); log.info("===== 请求结束 [userId={}, role={}] =====", userId, role); return result; @@ -111,4 +126,72 @@ public class RequestLogAspect { return args; } } + + /** + * 请求参数脱敏处理 + * 将敏感字段(如 password、token 等)替换为 *** + * + * @param original 原始参数对象 + * @return 脱敏后的 JSON 字符串 + */ + private String desensitize(Object original) { + if (original == null) { + return null; + } + try { + // 转换为 JSONObject 以便修改 + String jsonStr = JSON.toJSONString(original); + JSONObject jsonObject = JSON.parseObject(jsonStr); + if (jsonObject != null) { + maskSensitiveFields(jsonObject); + return jsonObject.toJSONString(); + } + return jsonStr; + } catch (Exception e) { + // 解析失败时返回原始 JSON + log.warn("请求参数脱敏失败:{}", e.getMessage()); + return JSON.toJSONString(original); + } + } + + /** + * 递归掩码敏感字段 + * + * @param jsonObject 要处理的 JSON 对象 + */ + private void maskSensitiveFields(JSONObject jsonObject) { + if (jsonObject == null) { + return; + } + for (String key : jsonObject.keySet()) { + if (isSensitiveField(key)) { + jsonObject.put(key, MASK); + } else { + // 递归处理嵌套的 JSONObject + Object value = jsonObject.get(key); + if (value instanceof JSONObject) { + maskSensitiveFields((JSONObject) value); + } + } + } + } + + /** + * 判断字段名是否为敏感字段 + * + * @param fieldName 字段名 + * @return true 如果是敏感字段 + */ + private boolean isSensitiveField(String fieldName) { + if (fieldName == null) { + return false; + } + String lowerFieldName = fieldName.toLowerCase(); + for (String sensitiveField : SENSITIVE_FIELDS) { + if (lowerFieldName.equals(sensitiveField.toLowerCase())) { + return true; + } + } + return false; + } }