feat: 日志添加浏览器和操作系统

This commit is contained in:
hxr
2024-06-27 00:26:29 +08:00
parent a0530dc380
commit 428a61e682
4 changed files with 95 additions and 55 deletions

View File

@@ -16,66 +16,70 @@ import java.net.UnknownHostException;
@Slf4j @Slf4j
public class IPUtils { public class IPUtils {
/** /**
* 获取IP地址 * 获取客户端IP地址
* 使用Nginx等反向代理软件 则不能通过request.getRemoteAddr()获取IP地址 * 如果通过了多级反向代理则取X-Forwarded-For头中第一个非unknown的有效IP地址
* 如果使用了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP地址X-Forwarded-For中第一个非unknown的有效IP字符串则为真实IP地址 *
* @param request HttpServletRequest请求对象
* @return 客户端IP地址
*/ */
public static String getIpAddr(HttpServletRequest request) { public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
if (request == null) { if (request == null) {
return ""; return "";
} }
ip = request.getHeader("x-forwarded-for");
if (checkIp(ip)) { String ip = request.getHeader("x-forwarded-for");
if (isIpInvalid(ip)) {
ip = request.getHeader("Proxy-Client-IP"); ip = request.getHeader("Proxy-Client-IP");
} }
if (checkIp(ip)) { if (isIpInvalid(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP"); ip = request.getHeader("WL-Proxy-Client-IP");
} }
if (checkIp(ip)) { if (isIpInvalid(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP"); ip = request.getHeader("HTTP_CLIENT_IP");
} }
if (checkIp(ip)) { if (isIpInvalid(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR"); ip = request.getHeader("HTTP_X_FORWARDED_FOR");
} }
if (checkIp(ip)) { if (isIpInvalid(ip)) {
ip = request.getRemoteAddr(); ip = request.getRemoteAddr();
// 检查是否为本地IP地址
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
// 根据网卡取本机配置的IP
ip = getLocalAddr(); ip = getLocalAddr();
} }
} }
} catch (Exception e) {
log.error("IPUtils ERROR, {}", e.getMessage());
}
//使用代理,则获取第一个IP地址 // 如果存在多个代理IP地址取第一个非unknown的有效IP地址
if (StrUtil.isNotBlank(ip) && ip.indexOf(",") > 0) { if (ip != null && ip.contains(",")) {
ip = ip.substring(0, ip.indexOf(",")); ip = ip.split(",")[0].trim();
} }
return ip; return ip;
} }
/**
private static boolean checkIp(String ip) { * 检查IP地址是否无效
String unknown = "unknown"; *
return StrUtil.isEmpty(ip) || ip.isEmpty() || unknown.equalsIgnoreCase(ip); * @param ip IP地址字符串
* @return 如果IP地址为空或"unknown"则返回true否则返回false
*/
private static boolean isIpInvalid(String ip) {
return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip);
} }
/** /**
* 获取本机IP地址 * 获取本机IP地址
*
* @return 本机IP地址字符串
*/ */
private static String getLocalAddr() { private static String getLocalAddr() {
try { try {
return InetAddress.getLocalHost().getHostAddress(); return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
log.error("InetAddress.getLocalHost()-error, {}", e.getMessage()); e.printStackTrace();
return "";
} }
return null;
} }
} }

View File

@@ -2,11 +2,9 @@ package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.time.LocalDateTime;
import com.youlai.system.common.base.BaseEntity;
import lombok.Data; import lombok.Data;
/** /**
@@ -41,16 +39,32 @@ public class SysLog implements Serializable {
*/ */
private String requestUri; private String requestUri;
/**
* 请求方法
*/
private String method;
/** /**
* IP 地址 * IP 地址
*/ */
private String ip; private String ip;
/**
* 浏览器
*/
private String browser;
/**
* 终端系统
*/
private String os;
/** /**
* 执行时间(毫秒) * 执行时间(毫秒)
*/ */
private Long executionTime; private Long executionTime;
/** /**
* 创建人ID * 创建人ID
*/ */
@@ -60,5 +74,7 @@ public class SysLog implements Serializable {
* 创建时间 * 创建时间
*/ */
@TableField(fill = FieldFill.INSERT) @TableField(fill = FieldFill.INSERT)
private Date createTime; private LocalDateTime createTime;
} }

View File

@@ -2,7 +2,10 @@ package com.youlai.system.plugin.syslog.aspect;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval; import cn.hutool.core.date.TimeInterval;
import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.useragent.Browser;
import cn.hutool.http.useragent.OS;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.youlai.system.common.util.IPUtils; import com.youlai.system.common.util.IPUtils;
import com.youlai.system.model.entity.SysLog; import com.youlai.system.model.entity.SysLog;
import com.youlai.system.plugin.syslog.annotation.LogAnnotation; import com.youlai.system.plugin.syslog.annotation.LogAnnotation;
@@ -38,7 +41,7 @@ public class LogAspect {
public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable { public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable {
TimeInterval timer = DateUtil.timer(); TimeInterval timer = DateUtil.timer();
Object proceed = joinPoint.proceed(); Object proceed = joinPoint.proceed();
long executionTime =timer.interval(); long executionTime = timer.interval();
// 创建日志对象 // 创建日志对象
SysLog log = new SysLog(); SysLog log = new SysLog();
@@ -47,17 +50,31 @@ public class LogAspect {
log.setRequestUri(request.getRequestURI()); log.setRequestUri(request.getRequestURI());
log.setIp(IPUtils.getIpAddr(request)); log.setIp(IPUtils.getIpAddr(request));
log.setExecutionTime(executionTime); log.setExecutionTime(executionTime);
log.setCreateBy(SecurityUtils.getUserId()); Long userId = SecurityUtils.getUserId();
log.setCreateBy(userId);
// 方法名
log.setMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
// 获取浏览器和终端系统信息
String userAgentString = request.getHeader("User-Agent");
UserAgent userAgent = UserAgentUtil.parse(userAgentString);
// 设置系统信息
log.setOs( userAgent.getOs().getName());
String browserName = userAgent.getBrowser().getName();
String browserVersion = userAgent.getBrowser().getVersion(userAgentString);
// 设置浏览器信息
String browserInfo = browserVersion != null && !browserVersion.isEmpty() ? browserName + " " + browserVersion : browserName;
log.setBrowser(browserInfo);
// 保存日志到数据库 // 保存日志到数据库
logService.save(log); logService.save(log);
return proceed; return proceed;
} }
} }

View File

@@ -57,13 +57,16 @@ public class AuthServiceImpl implements AuthService {
*/ */
@Override @Override
public LoginResult login(String username, String password) { public LoginResult login(String username, String password) {
// 认证用户信息 // 创建认证令牌对象
UsernamePasswordAuthenticationToken authenticationToken = UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username.toLowerCase().trim(), password); new UsernamePasswordAuthenticationToken(username.toLowerCase().trim(), password);
// 认证 // 执行用户认证
Authentication authentication = authenticationManager.authenticate(authenticationToken); Authentication authentication = authenticationManager.authenticate(authenticationToken);
// 认证成功生成Token // 认证成功生成JWT令牌
String accessToken = JwtUtils.createToken(authentication); String accessToken = JwtUtils.createToken(authentication);
// 将认证信息存入Security上下文便于在AOP如日志记录中获取当前用户信息
SecurityContextHolder.getContext().setAuthentication(authentication);
// 返回包含JWT令牌的登录结果
return LoginResult.builder() return LoginResult.builder()
.tokenType("Bearer") .tokenType("Bearer")
.accessToken(accessToken) .accessToken(accessToken)