refactor: 日志完善
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
package com.youlai.system.controller;
|
package com.youlai.system.controller;
|
||||||
|
|
||||||
import com.youlai.system.enums.LogTypeEnum;
|
import com.youlai.system.enums.LogModuleEnum;
|
||||||
import com.youlai.system.common.result.Result;
|
import com.youlai.system.common.result.Result;
|
||||||
import com.youlai.system.model.dto.CaptchaResult;
|
import com.youlai.system.model.dto.CaptchaResult;
|
||||||
import com.youlai.system.model.dto.LoginResult;
|
import com.youlai.system.model.dto.LoginResult;
|
||||||
@@ -30,7 +30,7 @@ public class AuthController {
|
|||||||
|
|
||||||
@Operation(summary = "登录")
|
@Operation(summary = "登录")
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@LogAnnotation(value = "登录", logType = LogTypeEnum.LOGIN)
|
@LogAnnotation(value = "登录", module = LogModuleEnum.LOGIN)
|
||||||
public Result<LoginResult> login(
|
public Result<LoginResult> login(
|
||||||
@Parameter(description = "用户名", example = "admin") @RequestParam String username,
|
@Parameter(description = "用户名", example = "admin") @RequestParam String username,
|
||||||
@Parameter(description = "密码", example = "123456") @RequestParam String password
|
@Parameter(description = "密码", example = "123456") @RequestParam String password
|
||||||
@@ -41,7 +41,7 @@ public class AuthController {
|
|||||||
|
|
||||||
@Operation(summary = "注销")
|
@Operation(summary = "注销")
|
||||||
@DeleteMapping("/logout")
|
@DeleteMapping("/logout")
|
||||||
@LogAnnotation(value = "注销", logType = LogTypeEnum.LOGIN)
|
@LogAnnotation(value = "注销", module = LogModuleEnum.LOGIN)
|
||||||
public Result logout() {
|
public Result logout() {
|
||||||
authService.logout();
|
authService.logout();
|
||||||
return Result.success();
|
return Result.success();
|
||||||
|
|||||||
51
src/main/java/com/youlai/system/enums/LogModuleEnum.java
Normal file
51
src/main/java/com/youlai/system/enums/LogModuleEnum.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package com.youlai.system.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志模块枚举
|
||||||
|
*
|
||||||
|
* @author Ray
|
||||||
|
* @since 2.10.0
|
||||||
|
*/
|
||||||
|
@Schema(enumAsRef = true)
|
||||||
|
@Getter
|
||||||
|
public enum LogModuleEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
LOGIN("登录"),
|
||||||
|
/**
|
||||||
|
* 用户模块
|
||||||
|
*/
|
||||||
|
USER("用户模块"),
|
||||||
|
/**
|
||||||
|
* 部门模块
|
||||||
|
*/
|
||||||
|
DEPT("部门模块"),
|
||||||
|
/**
|
||||||
|
* 角色模块
|
||||||
|
*/
|
||||||
|
ROLE("角色模块"),
|
||||||
|
/**
|
||||||
|
* 菜单模块
|
||||||
|
*/
|
||||||
|
MENU("菜单模块"),
|
||||||
|
/**
|
||||||
|
* 字典模块
|
||||||
|
*/
|
||||||
|
DICT("字典模块"),
|
||||||
|
|
||||||
|
OTHER("其他")
|
||||||
|
;
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String moduleName;
|
||||||
|
|
||||||
|
LogModuleEnum(String moduleName) {
|
||||||
|
this.moduleName = moduleName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.youlai.system.enums;
|
|
||||||
|
|
||||||
import com.youlai.system.common.base.IBaseEnum;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志类型枚举
|
|
||||||
*
|
|
||||||
* @author Ray
|
|
||||||
* @since 2.10.0
|
|
||||||
*/
|
|
||||||
@Schema(enumAsRef = true)
|
|
||||||
@Getter
|
|
||||||
public enum LogTypeEnum implements IBaseEnum<Integer> {
|
|
||||||
|
|
||||||
OPERATION(1, "操作日志"),
|
|
||||||
LOGIN (2, "登录日志");
|
|
||||||
|
|
||||||
private final Integer value;
|
|
||||||
|
|
||||||
private final String label;
|
|
||||||
|
|
||||||
LogTypeEnum(Integer value, String label) {
|
|
||||||
this.value = value;
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ import lombok.Getter;
|
|||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @since 2022/4/23 9:36
|
* @since 2022/4/23 9:36
|
||||||
*/
|
*/
|
||||||
|
@Getter
|
||||||
public enum MenuTypeEnum implements IBaseEnum<Integer> {
|
public enum MenuTypeEnum implements IBaseEnum<Integer> {
|
||||||
|
|
||||||
NULL(0, null),
|
NULL(0, null),
|
||||||
@@ -19,13 +19,12 @@ public enum MenuTypeEnum implements IBaseEnum<Integer> {
|
|||||||
EXTLINK(3, "外链"),
|
EXTLINK(3, "外链"),
|
||||||
BUTTON(4, "按钮");
|
BUTTON(4, "按钮");
|
||||||
|
|
||||||
@Getter
|
// Mybatis-Plus 提供注解表示插入数据库时插入该值
|
||||||
@EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
|
@EnumValue
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
@Getter
|
|
||||||
// @JsonValue // 表示对枚举序列化时返回此字段
|
// @JsonValue // 表示对枚举序列化时返回此字段
|
||||||
private String label;
|
private final String label;
|
||||||
|
|
||||||
MenuTypeEnum(Integer value, String label) {
|
MenuTypeEnum(Integer value, String label) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ 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 com.youlai.system.enums.LogModuleEnum;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,33 +23,52 @@ public class SysLog implements Serializable {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志类型
|
* 日志模块
|
||||||
*
|
|
||||||
* @see com.youlai.system.enums.LogTypeEnum
|
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private LogModuleEnum module;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志标题
|
* 日志内容
|
||||||
*/
|
*/
|
||||||
private String title;
|
private String content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求路径
|
* 请求路径
|
||||||
*/
|
*/
|
||||||
private String requestUri;
|
private String requestUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IP 地址
|
* IP 地址
|
||||||
*/
|
*/
|
||||||
private String ip;
|
private String ip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地区
|
||||||
|
*/
|
||||||
|
private String region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器
|
||||||
|
*/
|
||||||
|
private String browser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 终端系统
|
||||||
|
*/
|
||||||
|
private String os;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行时间(毫秒)
|
* 执行时间(毫秒)
|
||||||
*/
|
*/
|
||||||
private Long executionTime;
|
private Long executionTime;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建人ID
|
* 创建人ID
|
||||||
*/
|
*/
|
||||||
@@ -60,5 +78,7 @@ public class SysLog implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField(fill = FieldFill.INSERT)
|
@TableField(fill = FieldFill.INSERT)
|
||||||
private Date createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.youlai.system.plugin.syslog.annotation;
|
package com.youlai.system.plugin.syslog.annotation;
|
||||||
|
|
||||||
import com.youlai.system.enums.LogTypeEnum;
|
import com.youlai.system.enums.LogModuleEnum;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ public @interface LogAnnotation {
|
|||||||
|
|
||||||
String value() default "";
|
String value() default "";
|
||||||
|
|
||||||
LogTypeEnum logType() default LogTypeEnum.OPERATION;
|
LogModuleEnum module() ;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,12 @@ 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.core.util.StrUtil;
|
||||||
|
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.constant.SecurityConstants;
|
||||||
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;
|
||||||
@@ -9,6 +15,7 @@ import com.youlai.system.security.util.SecurityUtils;
|
|||||||
import com.youlai.system.service.SysLogService;
|
import com.youlai.system.service.SysLogService;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
@@ -24,6 +31,7 @@ import org.springframework.stereotype.Component;
|
|||||||
@Aspect
|
@Aspect
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
public class LogAspect {
|
public class LogAspect {
|
||||||
|
|
||||||
private final SysLogService logService;
|
private final SysLogService logService;
|
||||||
@@ -35,19 +43,46 @@ public class LogAspect {
|
|||||||
|
|
||||||
@Around("logPointcut() && @annotation(logAnnotation)")
|
@Around("logPointcut() && @annotation(logAnnotation)")
|
||||||
public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable {
|
public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable {
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
|
||||||
|
Long userId = null;
|
||||||
|
// 非登录请求获取用户ID,登录请求在登录成功后(joinPoint.proceed())获取用户ID
|
||||||
|
if (!SecurityConstants.LOGIN_PATH.equals(requestURI)) {
|
||||||
|
userId = SecurityUtils.getUserId();
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
log.setType(logAnnotation.logType().getValue());
|
|
||||||
log.setTitle(logAnnotation.value());
|
|
||||||
log.setRequestUri(request.getRequestURI());
|
|
||||||
log.setIp(IPUtils.getIpAddr(request));
|
|
||||||
log.setExecutionTime(executionTime);
|
|
||||||
log.setCreateBy(SecurityUtils.getUserId());
|
|
||||||
|
|
||||||
|
log.setModule(logAnnotation.module());
|
||||||
|
log.setContent(logAnnotation.value());
|
||||||
|
log.setRequestUri(requestURI);
|
||||||
|
// 登录方法需要在登录成功后获取用户ID
|
||||||
|
if (userId == null) {
|
||||||
|
userId = SecurityUtils.getUserId();
|
||||||
|
}
|
||||||
|
log.setCreateBy(userId);
|
||||||
|
String ipAddr = IPUtils.getIpAddr(request);
|
||||||
|
if (StrUtil.isNotBlank(ipAddr)) {
|
||||||
|
log.setIp(ipAddr);
|
||||||
|
String region = IPUtils.getRegion(ipAddr);
|
||||||
|
log.setRegion(region);
|
||||||
|
}
|
||||||
|
log.setExecutionTime(executionTime);
|
||||||
|
// 方法名
|
||||||
|
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 browserInfo = userAgent.getBrowser().getName() + " " + userAgent.getBrowser().getVersion(userAgentString);
|
||||||
|
log.setBrowser(browserInfo);
|
||||||
// 保存日志到数据库
|
// 保存日志到数据库
|
||||||
logService.save(log);
|
logService.save(log);
|
||||||
|
|
||||||
@@ -55,8 +90,4 @@ public class LogAspect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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