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
public class IPUtils {
/**
* 获取IP地址
* 使用Nginx等反向代理软件 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP地址X-Forwarded-For中第一个非unknown的有效IP字符串则为真实IP地址
* 获取客户端IP地址
* 如果通过了多级反向代理则取X-Forwarded-For头中第一个非unknown的有效IP地址
*
* @param request HttpServletRequest请求对象
* @return 客户端IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
if (request == null) {
return "";
}
ip = request.getHeader("x-forwarded-for");
if (checkIp(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (checkIp(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (checkIp(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (checkIp(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (checkIp(ip)) {
ip = request.getRemoteAddr();
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
// 根据网卡取本机配置的IP
ip = getLocalAddr();
}
}
} catch (Exception e) {
log.error("IPUtils ERROR, {}", e.getMessage());
if (request == null) {
return "";
}
//使用代理则获取第一个IP地址
if (StrUtil.isNotBlank(ip) && ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
String ip = request.getHeader("x-forwarded-for");
if (isIpInvalid(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (isIpInvalid(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (isIpInvalid(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (isIpInvalid(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (isIpInvalid(ip)) {
ip = request.getRemoteAddr();
// 检查是否为本地IP地址
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
ip = getLocalAddr();
}
}
// 如果存在多个代理IP地址取第一个非unknown的有效IP地址
if (ip != null && ip.contains(",")) {
ip = ip.split(",")[0].trim();
}
return ip;
}
private static boolean checkIp(String ip) {
String unknown = "unknown";
return StrUtil.isEmpty(ip) || ip.isEmpty() || unknown.equalsIgnoreCase(ip);
/**
* 检查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() {
try {
return InetAddress.getLocalHost().getHostAddress();
} 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 java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import com.youlai.system.common.base.BaseEntity;
import lombok.Data;
/**
@@ -41,16 +39,32 @@ public class SysLog implements Serializable {
*/
private String requestUri;
/**
* 请求方法
*/
private String method;
/**
* IP 地址
*/
private String ip;
/**
* 浏览器
*/
private String browser;
/**
* 终端系统
*/
private String os;
/**
* 执行时间(毫秒)
*/
private Long executionTime;
/**
* 创建人ID
*/
@@ -60,5 +74,7 @@ public class SysLog implements Serializable {
* 创建时间
*/
@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.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.model.entity.SysLog;
import com.youlai.system.plugin.syslog.annotation.LogAnnotation;
@@ -38,7 +41,7 @@ public class LogAspect {
public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable {
TimeInterval timer = DateUtil.timer();
Object proceed = joinPoint.proceed();
long executionTime =timer.interval();
long executionTime = timer.interval();
// 创建日志对象
SysLog log = new SysLog();
@@ -47,17 +50,31 @@ public class LogAspect {
log.setRequestUri(request.getRequestURI());
log.setIp(IPUtils.getIpAddr(request));
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);
return proceed;
}
}

View File

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