From 25df88d0ab9d7444ed1d162b9efa1259ac2f6f66 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期一, 27 四月 2026 10:13:53 +0800
Subject: [PATCH] 小程序对接finish
---
backend/src/main/java/com/sinata/appointment/audit/OpLogAuditAspect.java | 156 +++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 143 insertions(+), 13 deletions(-)
diff --git a/backend/src/main/java/com/sinata/appointment/audit/OpLogAuditAspect.java b/backend/src/main/java/com/sinata/appointment/audit/OpLogAuditAspect.java
index 1572151..c8ce5e1 100644
--- a/backend/src/main/java/com/sinata/appointment/audit/OpLogAuditAspect.java
+++ b/backend/src/main/java/com/sinata/appointment/audit/OpLogAuditAspect.java
@@ -1,16 +1,30 @@
package com.sinata.appointment.audit;
import cn.dev33.satoken.stp.StpUtil;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sinata.appointment.config.MiniStpUtil;
import com.sinata.appointment.service.OpLogApplicationService;
+import jakarta.servlet.http.HttpServletRequest;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.LinkedHashMap;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import java.lang.reflect.Method;
import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.util.StringUtils;
/**
- * 配置类写操作审计(示例):复杂场景可在 ApplicationService 内显式记录。
+ * 统一记录控制器写操作日志。
*/
@Slf4j
@Aspect
@@ -19,23 +33,139 @@
public class OpLogAuditAspect {
private final OpLogApplicationService opLogApplicationService;
+ private final ObjectMapper objectMapper;
- @AfterReturning(
- pointcut =
- "execution(* com.sinata.appointment.service.ConfigApplicationService.save*(..))",
- returning = "ret")
- public void afterConfigSave(JoinPoint jp, Object ret) {
+ @Pointcut("within(com.sinata.appointment.controller..*)")
+ public void controllerWriteOperation() {}
+
+ @AfterReturning(pointcut = "controllerWriteOperation()", returning = "ret")
+ public void afterWrite(JoinPoint jp, Object ret) {
try {
- Long op = StpUtil.isLogin() ? StpUtil.getLoginIdAsLong() : null;
+ HttpServletRequest request = currentRequest();
+ if (request == null) {
+ return;
+ }
+ if (!isWriteMethod(request.getMethod())) {
+ return;
+ }
+ String uri = request.getRequestURI();
+ String sourceType = resolveSourceType(uri);
+ if (!StringUtils.hasText(sourceType)) {
+ return;
+ }
+ Long operatorUserId = resolveOperatorUserId(sourceType);
opLogApplicationService.recordAsync(
- op,
- "CONFIG",
- jp.getSignature().getName(),
- jp.getArgs().length > 0 ? jp.getArgs()[0].getClass().getSimpleName() : "UNKNOWN",
- "",
- "{}");
+ sourceType,
+ operatorUserId,
+ resolveModule(jp, uri),
+ resolveAction(jp),
+ jp.getTarget().getClass().getSimpleName(),
+ uri,
+ buildDetailJson(request, jp));
} catch (Exception e) {
log.debug("audit skip: {}", e.getMessage());
}
}
+
+ private boolean isWriteMethod(String method) {
+ if (!StringUtils.hasText(method)) {
+ return false;
+ }
+ return "POST".equalsIgnoreCase(method)
+ || "PUT".equalsIgnoreCase(method)
+ || "PATCH".equalsIgnoreCase(method)
+ || "DELETE".equalsIgnoreCase(method);
+ }
+
+ private HttpServletRequest currentRequest() {
+ RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+ if (attributes instanceof ServletRequestAttributes servletRequestAttributes) {
+ return servletRequestAttributes.getRequest();
+ }
+ return null;
+ }
+
+ private String resolveSourceType(String uri) {
+ if (!StringUtils.hasText(uri)) {
+ return null;
+ }
+ if (uri.startsWith("/api/mini/")) {
+ return OpLogApplicationService.SOURCE_MINI_EMPLOYEE;
+ }
+ if (uri.startsWith("/api/")) {
+ return OpLogApplicationService.SOURCE_ADMIN;
+ }
+ return null;
+ }
+
+ private Long resolveOperatorUserId(String sourceType) {
+ if (OpLogApplicationService.SOURCE_MINI_EMPLOYEE.equals(sourceType)) {
+ return MiniStpUtil.isLogin() ? MiniStpUtil.getLoginIdAsLong() : null;
+ }
+ return StpUtil.isLogin() ? StpUtil.getLoginIdAsLong() : null;
+ }
+
+ private String resolveModule(JoinPoint jp, String uri) {
+ Tag tag = jp.getTarget().getClass().getAnnotation(Tag.class);
+ if (tag != null && StringUtils.hasText(tag.name())) {
+ return tag.name().trim();
+ }
+ if (!StringUtils.hasText(uri)) {
+ return "UNKNOWN";
+ }
+ String trimmed = uri.startsWith("/api/") ? uri.substring(5) : uri;
+ String[] segments = trimmed.split("/");
+ if (segments.length >= 2 && "mini".equalsIgnoreCase(segments[0])) {
+ return segments[1].toUpperCase();
+ }
+ return segments.length > 0 ? segments[0].toUpperCase() : "UNKNOWN";
+ }
+
+ private String resolveAction(JoinPoint jp) {
+ if (jp.getSignature() instanceof MethodSignature methodSignature) {
+ Method method = methodSignature.getMethod();
+ Operation operation = method.getAnnotation(Operation.class);
+ if (operation != null && StringUtils.hasText(operation.summary())) {
+ return operation.summary().trim();
+ }
+ }
+ return jp.getSignature().getName();
+ }
+
+ private String buildDetailJson(HttpServletRequest request, JoinPoint jp) {
+ Map<String, Object> payload = new LinkedHashMap<>();
+ payload.put("method", request.getMethod());
+ payload.put("uri", request.getRequestURI());
+ payload.put("handler", jp.getSignature().toShortString());
+ payload.put("args", summarizeArgs(jp.getArgs()));
+ try {
+ return objectMapper.writeValueAsString(payload);
+ } catch (Exception ex) {
+ return "{\"uri\":\"" + request.getRequestURI() + "\"}";
+ }
+ }
+
+ private Object[] summarizeArgs(Object[] args) {
+ if (args == null || args.length == 0) {
+ return new Object[0];
+ }
+ Object[] summarized = new Object[args.length];
+ for (int i = 0; i < args.length; i++) {
+ Object arg = args[i];
+ if (arg == null) {
+ summarized[i] = null;
+ continue;
+ }
+ if (arg instanceof String || arg instanceof Number || arg instanceof Boolean) {
+ String value = String.valueOf(arg);
+ summarized[i] =
+ value.length() > 60
+ ? value.substring(0, 60) + "..."
+ : value;
+ continue;
+ }
+ summarized[i] = arg.getClass().getSimpleName();
+ }
+ return summarized;
+ }
}
--
Gitblit v1.7.1