From 428a61e6822a6f4ea83738e26899d474a1910197 Mon Sep 17 00:00:00 2001 From: hxr <1490493387@qq.com> Date: Thu, 27 Jun 2024 00:26:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=97=A5=E5=BF=97=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B5=8F=E8=A7=88=E5=99=A8=E5=92=8C=E6=93=8D=E4=BD=9C=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youlai/system/common/util/IPUtils.java | 86 ++++++++++--------- .../youlai/system/model/entity/SysLog.java | 24 +++++- .../plugin/syslog/aspect/LogAspect.java | 31 +++++-- .../system/service/impl/AuthServiceImpl.java | 9 +- 4 files changed, 95 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/youlai/system/common/util/IPUtils.java b/src/main/java/com/youlai/system/common/util/IPUtils.java index ab65d7f9..1af51f5d 100644 --- a/src/main/java/com/youlai/system/common/util/IPUtils.java +++ b/src/main/java/com/youlai/system/common/util/IPUtils.java @@ -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; } - } diff --git a/src/main/java/com/youlai/system/model/entity/SysLog.java b/src/main/java/com/youlai/system/model/entity/SysLog.java index a79095e3..f8de37ae 100644 --- a/src/main/java/com/youlai/system/model/entity/SysLog.java +++ b/src/main/java/com/youlai/system/model/entity/SysLog.java @@ -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; + + } \ No newline at end of file diff --git a/src/main/java/com/youlai/system/plugin/syslog/aspect/LogAspect.java b/src/main/java/com/youlai/system/plugin/syslog/aspect/LogAspect.java index 7b17289e..5815da79 100644 --- a/src/main/java/com/youlai/system/plugin/syslog/aspect/LogAspect.java +++ b/src/main/java/com/youlai/system/plugin/syslog/aspect/LogAspect.java @@ -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; } - - - - } diff --git a/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java b/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java index 9c3bd48f..bfa64ec4 100644 --- a/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java +++ b/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java @@ -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)