package com.realtime.protection.configuration.response; import com.realtime.protection.ProtectionApplication; import com.realtime.protection.configuration.entity.user.User; import com.realtime.protection.configuration.entity.user.UserFull; import jakarta.servlet.http.HttpSession; import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientRequestException; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import reactor.core.publisher.Mono; import java.util.Enumeration; /** * 修改人: Fulian Li * 功能:执行日志审计 **/ @RestControllerAdvice(basePackageClasses = {ProtectionApplication.class}) @Slf4j @ControllerAdvice public class AuditAdvice implements ResponseBodyAdvice { private final WebClient webClient = WebClient .builder() .baseUrl("http://39.105.210.156:8090/chanct-log/audit-xgs") // .baseUrl("http://10.58.44.241:1888/api/chanct-log/audit-xgs") .build(); @Data @AllArgsConstructor private static class AuditRes{ private AuditData auditBase; } @Data @AllArgsConstructor private static class AuditData { private String userId; private String deptId; private String userName; private String deptName; private String menu; private String action; private String res; private String content; private String userIp; } @Override public boolean supports(MethodParameter returnType, Class> converterType) { // return false; return true; } @Override public ResponseResult beforeBodyWrite(ResponseResult body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { // 可以不发送query的请求,数据量太大 if (request.getURI().getPath().contains("query")){ return body; } AuditData auditData = getAuditData(body, request); AuditRes auditRes = new AuditRes(auditData); log.info("auditData-----------:"+auditData); Mono mono = webClient .post() .uri("/save") .bodyValue(auditRes) .exchangeToMono(res -> { if (res.statusCode().equals(HttpStatus.OK)) { log.info("发送审计日志成功:{}",res.statusCode()); return res.bodyToMono(String.class); } log.info("发送审计日志失败:{}",res.statusCode()); return null; }) .doOnError(WebClientRequestException.class, err -> log.warn("审计服务器遭遇异常{}", err.getMessage())); mono.subscribe(AuditAdvice::handleMono); return body; } // 解析 X-Forwarded-For 头中的第一个 IP 地址 private static String extractFirstIpAddress(String xForwardedForHeader) { if (xForwardedForHeader != null) { // 根据逗号分隔获取第一个 IP 地址 String[] ips = xForwardedForHeader.trim().split("\\s*,\\s*"); return ips[0]; } return null; } @NotNull private static AuditData getAuditData(ResponseResult body, ServerHttpRequest request) { HttpSession session = ((ServletServerHttpRequest) request).getServletRequest().getSession(); AuditData auditData; if(session==null || session.getAttribute("user")==null){ auditData = new AuditData( "0000000","0000000","NSADD管理员","组织树", request.getURI().getPath(), request.getMethod().toString(), body.getCode()==200?"成功":"失败", body.getData().toString(), extractFirstIpAddress(request.getHeaders().getFirst("X-Forwarded-For")) ); }else { UserFull user = (UserFull) session.getAttribute("user"); auditData = new AuditData( user.uid, user.getOrgCode(),user.name, user.getOrgName(), request.getURI().getPath(), request.getMethod().toString(), body.getCode()==200?"成功":"失败", body.getData().toString(), extractFirstIpAddress(request.getHeaders().getFirst("X-Forwarded-For")) ); } return auditData; } private static void handleMono(String result) { log.info("审计服务器返回结果:" + result); } }