feat: implement OperationLogAspect with complete IP extraction logic
This commit is contained in:
+125
@@ -0,0 +1,125 @@
|
||||
package cn.novalon.manage.sys.audit;
|
||||
|
||||
import cn.novalon.manage.sys.core.domain.OperationLog;
|
||||
import cn.novalon.manage.sys.core.service.IOperationLogService;
|
||||
import cn.novalon.manage.sys.util.IpUtils;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class OperationLogAspect {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OperationLogAspect.class);
|
||||
private final IOperationLogService logService;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public OperationLogAspect(IOperationLogService logService, ObjectMapper objectMapper) {
|
||||
this.logService = logService;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@Around("@annotation(operationLogAnnotation)")
|
||||
public Object around(ProceedingJoinPoint point, cn.novalon.manage.sys.audit.OperationLog operationLogAnnotation) throws Throwable {
|
||||
long startTime = System.currentTimeMillis();
|
||||
ServerRequest serverRequest = extractServerRequest(point.getArgs());
|
||||
String username = getCurrentUsername();
|
||||
String ip = IpUtils.getClientIp(serverRequest);
|
||||
String method = point.getSignature().toShortString();
|
||||
String params = serializeParams(point.getArgs());
|
||||
Object result = null;
|
||||
String status = "0";
|
||||
String errorMsg = null;
|
||||
try {
|
||||
result = point.proceed();
|
||||
if (result instanceof Mono) {
|
||||
return ((Mono<?>) result)
|
||||
.doOnSuccess(res -> {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
saveLogAsync(operationLogAnnotation, username, ip, method, params, res, duration, "0", null);
|
||||
})
|
||||
.doOnError(error -> {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
saveLogAsync(operationLogAnnotation, username, ip, method, params, null, duration, "1", error.getMessage());
|
||||
});
|
||||
}
|
||||
return result;
|
||||
} catch (Throwable error) {
|
||||
status = "1";
|
||||
errorMsg = error.getMessage();
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
saveLogAsync(operationLogAnnotation, username, ip, method, params, null, duration, status, errorMsg);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private ServerRequest extractServerRequest(Object[] args) {
|
||||
if (args == null || args.length == 0) return null;
|
||||
for (Object arg : args) {
|
||||
if (arg instanceof ServerRequest) return (ServerRequest) arg;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getCurrentUsername() {
|
||||
try {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(ctx -> ctx.getAuthentication().getPrincipal())
|
||||
.cast(String.class)
|
||||
.blockOptional()
|
||||
.orElse("system");
|
||||
} catch (Exception e) {
|
||||
logger.warn("考试当前用命名失败: {}", e.getMessage());
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
|
||||
private String serializeParams(Object[] args) {
|
||||
try {
|
||||
if (args == null || args.length == 0) return null;
|
||||
return objectMapper.writeValueAsString(args);
|
||||
} catch (Exception e) {
|
||||
logger.warn("处的包正数失败: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String serializeResult(Object result) {
|
||||
try {
|
||||
if (result == null) return null;
|
||||
return objectMapper.writeValueAsString(result);
|
||||
} catch (Exception e) {
|
||||
logger.warn("处皅包正数失败: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveLogAsync(cn.novalon.manage.sys.audit.OperationLog annotation, String username, String ip, String method, String params, Object result, long duration, String status, String errorMsg) {
|
||||
Mono.fromRunnable(() -> {
|
||||
OperationLog log = new OperationLog();
|
||||
log.setUsername(username);
|
||||
log.setOperation(annotation.module() + " - " + annotation.operation());
|
||||
log.setMethod(method);
|
||||
log.setParams(params);
|
||||
log.setResult(serializeResult(result));
|
||||
log.setIp(ip);
|
||||
log.setDuration(duration);
|
||||
log.setStatus(status);
|
||||
log.setErrorMsg(errorMsg);
|
||||
logService.save(log)
|
||||
.doOnSuccess(saved -> logger.debug("操作实跋信息成功退: {} - {}", annotation.module(), annotation.operation()))
|
||||
.doOnError(error -> logger.error("作实跋信息成功退: {}", error.getMessage()))
|
||||
.subscribe();
|
||||
})
|
||||
.subscribeOn(Schedulers.boundedElastic())
|
||||
.subscribe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package cn.novalon.manage.sys.util;
|
||||
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
public class IpUtils {
|
||||
private static final String UNKNOWN = "unknown";
|
||||
private static final String LOCALHOST_IP = "127.0.0.1";
|
||||
private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
|
||||
|
||||
public static String getClientIp(ServerRequest request) {
|
||||
if (request == null) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
String ip = getXForwardedForIp(request);
|
||||
if (isValidIp(ip)) {
|
||||
return ip;
|
||||
}
|
||||
ip = getXRealIp(request);
|
||||
if (isValidIp(ip)) {
|
||||
return ip;
|
||||
}
|
||||
ip = getRemoteAddress(request);
|
||||
if (isValidIp(ip)) {
|
||||
return ip;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private static String getXForwardedForIp(ServerRequest request) {
|
||||
String ip = request.headers().firstHeader("X-Forwarded-For");
|
||||
if (ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
|
||||
int index = ip.indexOf(",");
|
||||
if (index != -1) {
|
||||
return ip.substring(0, index);
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getXRealIp(ServerRequest request) {
|
||||
String ip = request.headers().firstHeader("X-Real-IP");
|
||||
if (ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
|
||||
return ip;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getRemoteAddress(ServerRequest request) {
|
||||
Optional<InetSocketAddress> remoteAddress = request.remoteAddress();
|
||||
if (remoteAddress.isPresent()) {
|
||||
String ip = remoteAddress.get().getAddress().getHostAddress();
|
||||
if (LOCALHOST_IPV6.equals(ip)) {
|
||||
ip = LOCALHOST_IP;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isValidIp(String ip) {
|
||||
return ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user