feat: 日志添加浏览器和操作系统
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user