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