Commit 083dac77e1ef5e6bc04ce09fe03c31258e2ed93a
1 parent
cbb11986
接入登陆日志
Showing
17 changed files
with
236 additions
and
52 deletions
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
| 1 | package com.ruoyi.web.controller.monitor; | 1 | package com.ruoyi.web.controller.monitor; |
| 2 | 2 | ||
| 3 | import java.util.List; | 3 | import java.util.List; |
| 4 | + | ||
| 4 | import org.springframework.beans.factory.annotation.Autowired; | 5 | import org.springframework.beans.factory.annotation.Autowired; |
| 5 | import org.springframework.security.access.prepost.PreAuthorize; | 6 | import org.springframework.security.access.prepost.PreAuthorize; |
| 6 | import org.springframework.web.bind.annotation.DeleteMapping; | 7 | import org.springframework.web.bind.annotation.DeleteMapping; |
| @@ -24,15 +25,14 @@ import com.ruoyi.system.service.ISysLogininforService; | @@ -24,15 +25,14 @@ import com.ruoyi.system.service.ISysLogininforService; | ||
| 24 | */ | 25 | */ |
| 25 | @RestController | 26 | @RestController |
| 26 | @RequestMapping("/monitor/logininfor") | 27 | @RequestMapping("/monitor/logininfor") |
| 27 | -public class SysLogininforController extends BaseController | ||
| 28 | -{ | 28 | +public class SysLogininforController extends BaseController { |
| 29 | + | ||
| 29 | @Autowired | 30 | @Autowired |
| 30 | private ISysLogininforService logininforService; | 31 | private ISysLogininforService logininforService; |
| 31 | 32 | ||
| 32 | @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") | 33 | @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") |
| 33 | @GetMapping("/list") | 34 | @GetMapping("/list") |
| 34 | - public TableDataInfo list(SysLogininfor logininfor) | ||
| 35 | - { | 35 | + public TableDataInfo list(SysLogininfor logininfor) { |
| 36 | startPage(); | 36 | startPage(); |
| 37 | List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); | 37 | List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |
| 38 | return getDataTable(list); | 38 | return getDataTable(list); |
| @@ -41,8 +41,7 @@ public class SysLogininforController extends BaseController | @@ -41,8 +41,7 @@ public class SysLogininforController extends BaseController | ||
| 41 | @Log(title = "登录日志", businessType = BusinessType.EXPORT) | 41 | @Log(title = "登录日志", businessType = BusinessType.EXPORT) |
| 42 | @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") | 42 | @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") |
| 43 | @GetMapping("/export") | 43 | @GetMapping("/export") |
| 44 | - public AjaxResult export(SysLogininfor logininfor) | ||
| 45 | - { | 44 | + public AjaxResult export(SysLogininfor logininfor) { |
| 46 | List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); | 45 | List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |
| 47 | ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); | 46 | ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); |
| 48 | return util.exportExcel(list, "登录日志"); | 47 | return util.exportExcel(list, "登录日志"); |
src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java
| @@ -24,9 +24,6 @@ import org.aspectj.lang.reflect.MethodSignature; | @@ -24,9 +24,6 @@ import org.aspectj.lang.reflect.MethodSignature; | ||
| 24 | import org.springframework.core.annotation.AnnotationUtils; | 24 | import org.springframework.core.annotation.AnnotationUtils; |
| 25 | import org.springframework.web.bind.annotation.RequestMapping; | 25 | import org.springframework.web.bind.annotation.RequestMapping; |
| 26 | import org.springframework.web.bind.annotation.RequestMethod; | 26 | import org.springframework.web.bind.annotation.RequestMethod; |
| 27 | -import org.springframework.web.context.request.RequestAttributes; | ||
| 28 | -import org.springframework.web.context.request.RequestContextHolder; | ||
| 29 | -import org.springframework.web.context.request.ServletRequestAttributes; | ||
| 30 | import org.springframework.web.multipart.MultipartFile; | 27 | import org.springframework.web.multipart.MultipartFile; |
| 31 | 28 | ||
| 32 | import javax.annotation.Resource; | 29 | import javax.annotation.Resource; |
| @@ -196,11 +193,10 @@ public class OperateLogAspect { | @@ -196,11 +193,10 @@ public class OperateLogAspect { | ||
| 196 | 193 | ||
| 197 | private static void fillRequestFields(SysOperateLogCreateReqVO operateLogVO) { | 194 | private static void fillRequestFields(SysOperateLogCreateReqVO operateLogVO) { |
| 198 | // 获得 Request 对象 | 195 | // 获得 Request 对象 |
| 199 | - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | ||
| 200 | - if (!(requestAttributes instanceof ServletRequestAttributes)) { | 196 | + HttpServletRequest request = ServletUtils.getRequest(); |
| 197 | + if (request == null) { | ||
| 201 | return; | 198 | return; |
| 202 | } | 199 | } |
| 203 | - HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); | ||
| 204 | // 补全请求信息 | 200 | // 补全请求信息 |
| 205 | operateLogVO.setRequestMethod(request.getMethod()); | 201 | operateLogVO.setRequestMethod(request.getMethod()); |
| 206 | operateLogVO.setRequestUrl(request.getRequestURI()); | 202 | operateLogVO.setRequestUrl(request.getRequestURI()); |
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java
| @@ -15,27 +15,23 @@ import javax.validation.constraints.Size; | @@ -15,27 +15,23 @@ import javax.validation.constraints.Size; | ||
| 15 | @Data | 15 | @Data |
| 16 | public class SysLoginLogBaseVO { | 16 | public class SysLoginLogBaseVO { |
| 17 | 17 | ||
| 18 | + @ApiModelProperty(value = "日志类型", required = true, example = "1", notes = "参见 SysLoginLogTypeEnum 枚举类") | ||
| 19 | + @NotNull(message = "日志类型不能为空") | ||
| 20 | + private Integer logType; | ||
| 21 | + | ||
| 18 | @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") | 22 | @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") |
| 19 | @NotEmpty(message = "链路追踪编号不能为空") | 23 | @NotEmpty(message = "链路追踪编号不能为空") |
| 20 | private String traceId; | 24 | private String traceId; |
| 21 | 25 | ||
| 22 | - @ApiModelProperty(value = "用户编号", required = true, example = "1024") | ||
| 23 | - @NotNull(message = "用户编号不能为空") | ||
| 24 | - private Long userId; | ||
| 25 | - | ||
| 26 | @ApiModelProperty(value = "用户账号", required = true, example = "yudao") | 26 | @ApiModelProperty(value = "用户账号", required = true, example = "yudao") |
| 27 | @NotBlank(message = "用户账号不能为空") | 27 | @NotBlank(message = "用户账号不能为空") |
| 28 | @Size(max = 30, message = "用户账号长度不能超过30个字符") | 28 | @Size(max = 30, message = "用户账号长度不能超过30个字符") |
| 29 | private String username; | 29 | private String username; |
| 30 | 30 | ||
| 31 | - | ||
| 32 | @ApiModelProperty(value = "登陆结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类") | 31 | @ApiModelProperty(value = "登陆结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类") |
| 33 | @NotNull(message = "登陆结果不能为空") | 32 | @NotNull(message = "登陆结果不能为空") |
| 34 | private Integer result; | 33 | private Integer result; |
| 35 | 34 | ||
| 36 | - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") | ||
| 37 | - private String content; | ||
| 38 | - | ||
| 39 | @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") | 35 | @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") |
| 40 | @NotEmpty(message = "用户 IP 不能为空") | 36 | @NotEmpty(message = "用户 IP 不能为空") |
| 41 | private String userIp; | 37 | private String userIp; |
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogCreateReqVO.java
| 1 | package cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog; | 1 | package cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO; | ||
| 4 | import io.swagger.annotations.ApiModel; | 3 | import io.swagger.annotations.ApiModel; |
| 5 | import lombok.Data; | 4 | import lombok.Data; |
| 6 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| @@ -11,5 +10,5 @@ import lombok.ToString; | @@ -11,5 +10,5 @@ import lombok.ToString; | ||
| 11 | @Data | 10 | @Data |
| 12 | @EqualsAndHashCode(callSuper = true) | 11 | @EqualsAndHashCode(callSuper = true) |
| 13 | @ToString(callSuper = true) | 12 | @ToString(callSuper = true) |
| 14 | -public class SysLoginLogCreateReqVO extends SysOperateLogCreateReqVO { | 13 | +public class SysLoginLogCreateReqVO extends SysLoginLogBaseVO { |
| 15 | } | 14 | } |
src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysLoginLogConvert.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.convert.logger; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||
| 4 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO; | ||
| 5 | +import org.mapstruct.Mapper; | ||
| 6 | +import org.mapstruct.factory.Mappers; | ||
| 7 | + | ||
| 8 | +@Mapper | ||
| 9 | +public interface SysLoginLogConvert { | ||
| 10 | + | ||
| 11 | + SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class); | ||
| 12 | + | ||
| 13 | + SysLoginLogDO convert(SysLoginLogCreateReqVO bean); | ||
| 14 | + | ||
| 15 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysLoginLogMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO; | ||
| 5 | +import org.apache.ibatis.annotations.Mapper; | ||
| 6 | + | ||
| 7 | +@Mapper | ||
| 8 | +public interface SysLoginLogMapper extends BaseMapperX<SysLoginLogDO> { | ||
| 9 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysLoginLogDO.java
| 1 | package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; | 1 | package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; |
| 2 | 2 | ||
| 3 | import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | 3 | import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; |
| 4 | -import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; | 4 | +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; |
| 5 | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; | 5 | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; |
| 6 | import com.baomidou.mybatisplus.annotation.TableName; | 6 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | +import lombok.ToString; | ||
| 7 | 10 | ||
| 8 | /** | 11 | /** |
| 9 | - * 系统访问记录表 | 12 | + * 登陆日志表 |
| 13 | + * | ||
| 14 | + * 注意,包括登陆和登出两种行为 | ||
| 10 | * | 15 | * |
| 11 | * @author ruoyi | 16 | * @author ruoyi |
| 12 | */ | 17 | */ |
| 13 | -@TableName("用户登陆日志") | 18 | +@TableName("sys_login_log") |
| 19 | +@Data | ||
| 20 | +@EqualsAndHashCode(callSuper = true) | ||
| 21 | +@ToString(callSuper = true) | ||
| 14 | public class SysLoginLogDO extends BaseDO { | 22 | public class SysLoginLogDO extends BaseDO { |
| 15 | 23 | ||
| 16 | /** | 24 | /** |
| @@ -18,15 +26,15 @@ public class SysLoginLogDO extends BaseDO { | @@ -18,15 +26,15 @@ public class SysLoginLogDO extends BaseDO { | ||
| 18 | */ | 26 | */ |
| 19 | private Long id; | 27 | private Long id; |
| 20 | /** | 28 | /** |
| 21 | - * 链路追踪编号 | 29 | + * 日志类型 |
| 30 | + * | ||
| 31 | + * 枚举 {@link SysLoginLogTypeEnum} | ||
| 22 | */ | 32 | */ |
| 23 | - private String traceId; | 33 | + private Integer logType; |
| 24 | /** | 34 | /** |
| 25 | - * 用户编号 | ||
| 26 | - * | ||
| 27 | - * 外键 {@link SysUserDO#getId()} | 35 | + * 链路追踪编号 |
| 28 | */ | 36 | */ |
| 29 | - private Long userId; | 37 | + private String traceId; |
| 30 | /** | 38 | /** |
| 31 | * 用户账号 | 39 | * 用户账号 |
| 32 | * | 40 | * |
| @@ -39,12 +47,10 @@ public class SysLoginLogDO extends BaseDO { | @@ -39,12 +47,10 @@ public class SysLoginLogDO extends BaseDO { | ||
| 39 | * 枚举 {@link SysLoginResultEnum} | 47 | * 枚举 {@link SysLoginResultEnum} |
| 40 | */ | 48 | */ |
| 41 | private Integer result; | 49 | private Integer result; |
| 42 | - | ||
| 43 | /** | 50 | /** |
| 44 | * 用户 IP | 51 | * 用户 IP |
| 45 | */ | 52 | */ |
| 46 | private String userIp; | 53 | private String userIp; |
| 47 | - | ||
| 48 | /** | 54 | /** |
| 49 | * 浏览器 UA | 55 | * 浏览器 UA |
| 50 | */ | 56 | */ |
src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
| @@ -13,6 +13,8 @@ public interface SysErrorCodeConstants { | @@ -13,6 +13,8 @@ public interface SysErrorCodeConstants { | ||
| 13 | ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); | 13 | ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); |
| 14 | ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用"); | 14 | ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用"); |
| 15 | ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登陆失败的兜底,位置原因 | 15 | ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登陆失败的兜底,位置原因 |
| 16 | + ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在"); | ||
| 17 | + ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确"); | ||
| 16 | 18 | ||
| 17 | // ========== TOKEN 模块 1002001000 ========== | 19 | // ========== TOKEN 模块 1002001000 ========== |
| 18 | ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期"); | 20 | ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期"); |
src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysLoginLogTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.enums.logger; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 登陆日志的类型枚举 | ||
| 8 | + */ | ||
| 9 | +@Getter | ||
| 10 | +@AllArgsConstructor | ||
| 11 | +public enum SysLoginLogTypeEnum { | ||
| 12 | + | ||
| 13 | + LOGIN(1), | ||
| 14 | + LOGOUT(2); | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 日志类型 | ||
| 18 | + */ | ||
| 19 | + private final Integer type; | ||
| 20 | + | ||
| 21 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysLoginResultEnum.java
| @@ -11,6 +11,12 @@ import lombok.Getter; | @@ -11,6 +11,12 @@ import lombok.Getter; | ||
| 11 | public enum SysLoginResultEnum { | 11 | public enum SysLoginResultEnum { |
| 12 | 12 | ||
| 13 | SUCCESS(0), // 成功 | 13 | SUCCESS(0), // 成功 |
| 14 | + BAD_CREDENTIALS(10), // 账号或密码不正确 | ||
| 15 | + USER_DISABLED(20), // 账号或密码不正确 | ||
| 16 | + CAPTCHA_NOT_FOUND(30), // 验证码不存在 | ||
| 17 | + CAPTCHA_CODE_ERROR(31), // 验证码不正确 | ||
| 18 | + | ||
| 19 | + UNKNOWN_ERROR(100), // 未知异常 | ||
| 14 | ; | 20 | ; |
| 15 | 21 | ||
| 16 | /** | 22 | /** |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
| @@ -3,16 +3,24 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl; | @@ -3,16 +3,24 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl; | ||
| 3 | import cn.hutool.core.util.IdUtil; | 3 | import cn.hutool.core.util.IdUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.dashboard.common.enums.CommonStatusEnum; |
| 6 | +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; | ||
| 6 | import cn.iocoder.dashboard.framework.security.config.SecurityProperties; | 7 | import cn.iocoder.dashboard.framework.security.config.SecurityProperties; |
| 7 | import cn.iocoder.dashboard.framework.security.core.LoginUser; | 8 | import cn.iocoder.dashboard.framework.security.core.LoginUser; |
| 9 | +import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; | ||
| 10 | +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||
| 8 | import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; | 11 | import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; |
| 9 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; | 12 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 10 | import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; | 13 | import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; |
| 14 | +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; | ||
| 15 | +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; | ||
| 11 | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; | 16 | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; |
| 12 | import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; | 17 | import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; |
| 18 | +import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; | ||
| 19 | +import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService; | ||
| 13 | import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; | 20 | import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; |
| 14 | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; | 21 | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; |
| 15 | import cn.iocoder.dashboard.util.date.DateUtils; | 22 | import cn.iocoder.dashboard.util.date.DateUtils; |
| 23 | +import cn.iocoder.dashboard.util.servlet.ServletUtils; | ||
| 16 | import io.jsonwebtoken.Claims; | 24 | import io.jsonwebtoken.Claims; |
| 17 | import io.jsonwebtoken.JwtException; | 25 | import io.jsonwebtoken.JwtException; |
| 18 | import lombok.extern.slf4j.Slf4j; | 26 | import lombok.extern.slf4j.Slf4j; |
| @@ -55,6 +63,10 @@ public class SysAuthServiceImpl implements SysAuthService { | @@ -55,6 +63,10 @@ public class SysAuthServiceImpl implements SysAuthService { | ||
| 55 | private SysUserService userService; | 63 | private SysUserService userService; |
| 56 | @Resource | 64 | @Resource |
| 57 | private SysPermissionService permissionService; | 65 | private SysPermissionService permissionService; |
| 66 | + @Resource | ||
| 67 | + private SysCaptchaService captchaService; | ||
| 68 | + @Resource | ||
| 69 | + private SysLoginLogService loginLogService; | ||
| 58 | 70 | ||
| 59 | @Resource | 71 | @Resource |
| 60 | private SysLoginUserRedisDAO loginUserRedisDAO; | 72 | private SysLoginUserRedisDAO loginUserRedisDAO; |
| @@ -87,7 +99,7 @@ public class SysAuthServiceImpl implements SysAuthService { | @@ -87,7 +99,7 @@ public class SysAuthServiceImpl implements SysAuthService { | ||
| 87 | @Override | 99 | @Override |
| 88 | public String login(String username, String password, String captchaUUID, String captchaCode) { | 100 | public String login(String username, String password, String captchaUUID, String captchaCode) { |
| 89 | // 判断验证码是否正确 | 101 | // 判断验证码是否正确 |
| 90 | - this.verifyCaptcha(captchaUUID, captchaCode); | 102 | + this.verifyCaptcha(username, captchaUUID, captchaCode); |
| 91 | 103 | ||
| 92 | // 使用账号密码,进行登陆。 | 104 | // 使用账号密码,进行登陆。 |
| 93 | LoginUser loginUser = this.login0(username, password); | 105 | LoginUser loginUser = this.login0(username, password); |
| @@ -102,18 +114,20 @@ public class SysAuthServiceImpl implements SysAuthService { | @@ -102,18 +114,20 @@ public class SysAuthServiceImpl implements SysAuthService { | ||
| 102 | return tokenService.createToken(sessionId); | 114 | return tokenService.createToken(sessionId); |
| 103 | } | 115 | } |
| 104 | 116 | ||
| 105 | - private void verifyCaptcha(String captchaUUID, String captchaCode) { | ||
| 106 | - // String verifyKey = Constants.CAPTCHA_CODE_KEY + captchaUUID; | ||
| 107 | -// String captcha = redisCache.getCacheObject(verifyKey); | ||
| 108 | -// redisCache.deleteObject(verifyKey); | ||
| 109 | -// if (captcha == null) { | ||
| 110 | -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); | ||
| 111 | -// throw new CaptchaExpireException(); | ||
| 112 | -// } | ||
| 113 | -// if (!code.equalsIgnoreCase(captcha)) { | ||
| 114 | -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); | ||
| 115 | -// throw new CaptchaException(); | ||
| 116 | -// } | 117 | + private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { |
| 118 | + String code = captchaService.getCaptchaCode(captchaUUID); | ||
| 119 | + // 验证码不存在 | ||
| 120 | + if (code == null) { | ||
| 121 | + this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_NOT_FOUND); | ||
| 122 | + throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND); | ||
| 123 | + } | ||
| 124 | + // 验证码不正确 | ||
| 125 | + if (!code.equals(captchaCode)) { | ||
| 126 | + this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_CODE_ERROR); | ||
| 127 | + throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR); | ||
| 128 | + } | ||
| 129 | + // 正确,所以要删除下验证码 | ||
| 130 | + captchaService.deleteCaptchaCode(captchaUUID); | ||
| 117 | } | 131 | } |
| 118 | 132 | ||
| 119 | private LoginUser login0(String username, String password) { | 133 | private LoginUser login0(String username, String password) { |
| @@ -124,22 +138,33 @@ public class SysAuthServiceImpl implements SysAuthService { | @@ -124,22 +138,33 @@ public class SysAuthServiceImpl implements SysAuthService { | ||
| 124 | // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 | 138 | // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 |
| 125 | authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); | 139 | authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); |
| 126 | } catch (BadCredentialsException badCredentialsException) { | 140 | } catch (BadCredentialsException badCredentialsException) { |
| 127 | - // TODO 日志优化 | ||
| 128 | -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); | 141 | + this.createLoginLog(username, SysLoginResultEnum.BAD_CREDENTIALS); |
| 129 | throw exception(AUTH_LOGIN_BAD_CREDENTIALS); | 142 | throw exception(AUTH_LOGIN_BAD_CREDENTIALS); |
| 130 | } catch (DisabledException disabledException) { | 143 | } catch (DisabledException disabledException) { |
| 131 | - // TODO 日志优化 | 144 | + this.createLoginLog(username, SysLoginResultEnum.USER_DISABLED); |
| 132 | throw exception(AUTH_LOGIN_USER_DISABLED); | 145 | throw exception(AUTH_LOGIN_USER_DISABLED); |
| 133 | } catch (AuthenticationException authenticationException) { | 146 | } catch (AuthenticationException authenticationException) { |
| 134 | - // TODO 日志优化 | 147 | + log.error("[login0][username({}) 发生未知异常]", username, authenticationException); |
| 148 | + this.createLoginLog(username, SysLoginResultEnum.UNKNOWN_ERROR); | ||
| 135 | throw exception(AUTH_LOGIN_FAIL_UNKNOWN); | 149 | throw exception(AUTH_LOGIN_FAIL_UNKNOWN); |
| 136 | } | 150 | } |
| 137 | - // TODO 需要优化 | ||
| 138 | -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); | 151 | + // 登陆成功 |
| 139 | Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); | 152 | Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); |
| 153 | + this.createLoginLog(username, SysLoginResultEnum.SUCCESS); | ||
| 140 | return (LoginUser) authentication.getPrincipal(); | 154 | return (LoginUser) authentication.getPrincipal(); |
| 141 | } | 155 | } |
| 142 | 156 | ||
| 157 | + private void createLoginLog(String username, SysLoginResultEnum loginResult) { | ||
| 158 | + SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO(); | ||
| 159 | + reqVO.setLogType(SysLoginLogTypeEnum.LOGIN.getType()); | ||
| 160 | + reqVO.setTraceId(TracerUtils.getTraceId()); | ||
| 161 | + reqVO.setUsername(username); | ||
| 162 | + reqVO.setUserAgent(ServletUtils.getUserAgent()); | ||
| 163 | + reqVO.setUserIp(ServletUtils.getClientIP()); | ||
| 164 | + reqVO.setResult(loginResult.getResult()); | ||
| 165 | + loginLogService.createLoginLog(reqVO); | ||
| 166 | + } | ||
| 167 | + | ||
| 143 | /** | 168 | /** |
| 144 | * 获得 User 拥有的角色编号数组 | 169 | * 获得 User 拥有的角色编号数组 |
| 145 | * | 170 | * |
src/main/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaService.java
| @@ -7,6 +7,26 @@ import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageR | @@ -7,6 +7,26 @@ import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageR | ||
| 7 | */ | 7 | */ |
| 8 | public interface SysCaptchaService { | 8 | public interface SysCaptchaService { |
| 9 | 9 | ||
| 10 | + /** | ||
| 11 | + * 获得验证码图片 | ||
| 12 | + * | ||
| 13 | + * @return 验证码图片 | ||
| 14 | + */ | ||
| 10 | SysCaptchaImageRespVO getCaptchaImage(); | 15 | SysCaptchaImageRespVO getCaptchaImage(); |
| 11 | 16 | ||
| 17 | + /** | ||
| 18 | + * 获得 uuid 对应的验证码 | ||
| 19 | + * | ||
| 20 | + * @param uuid 验证码编号 | ||
| 21 | + * @return 验证码 | ||
| 22 | + */ | ||
| 23 | + String getCaptchaCode(String uuid); | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 删除 uuid 对应的验证码 | ||
| 27 | + * | ||
| 28 | + * @param uuid 验证码编号 | ||
| 29 | + */ | ||
| 30 | + void deleteCaptchaCode(String uuid); | ||
| 31 | + | ||
| 12 | } | 32 | } |
src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java
| @@ -35,4 +35,14 @@ public class SysCaptchaServiceImpl implements SysCaptchaService { | @@ -35,4 +35,14 @@ public class SysCaptchaServiceImpl implements SysCaptchaService { | ||
| 35 | return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); | 35 | return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | + @Override | ||
| 39 | + public String getCaptchaCode(String uuid) { | ||
| 40 | + return captchaRedisDAO.get(uuid); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public void deleteCaptchaCode(String uuid) { | ||
| 45 | + captchaRedisDAO.delete(uuid); | ||
| 46 | + } | ||
| 47 | + | ||
| 38 | } | 48 | } |
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.logger; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 登陆日志 Service 接口 | ||
| 7 | + */ | ||
| 8 | +public interface SysLoginLogService { | ||
| 9 | + | ||
| 10 | + /** | ||
| 11 | + * 创建登陆日志 | ||
| 12 | + * | ||
| 13 | + * @param reqVO 日志信息 | ||
| 14 | + */ | ||
| 15 | + void createLoginLog(SysLoginLogCreateReqVO reqVO); | ||
| 16 | + | ||
| 17 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysLoginLogServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.logger.impl; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||
| 4 | +import cn.iocoder.dashboard.modules.system.convert.logger.SysLoginLogConvert; | ||
| 5 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysLoginLogMapper; | ||
| 6 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO; | ||
| 7 | +import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService; | ||
| 8 | +import org.springframework.stereotype.Service; | ||
| 9 | + | ||
| 10 | +import javax.annotation.Resource; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 登陆日志 Service 实现 | ||
| 14 | + */ | ||
| 15 | +@Service | ||
| 16 | +public class SysLoginLogServiceImpl implements SysLoginLogService { | ||
| 17 | + | ||
| 18 | + @Resource | ||
| 19 | + private SysLoginLogMapper loginLogMapper; | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public void createLoginLog(SysLoginLogCreateReqVO reqVO) { | ||
| 23 | + SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqVO); | ||
| 24 | + loginLogMapper.insert(loginLog); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +} |
src/main/java/cn/iocoder/dashboard/util/servlet/ServletUtils.java
| @@ -4,6 +4,9 @@ import cn.hutool.core.io.IoUtil; | @@ -4,6 +4,9 @@ import cn.hutool.core.io.IoUtil; | ||
| 4 | import cn.hutool.extra.servlet.ServletUtil; | 4 | import cn.hutool.extra.servlet.ServletUtil; |
| 5 | import com.alibaba.fastjson.JSON; | 5 | import com.alibaba.fastjson.JSON; |
| 6 | import org.springframework.http.MediaType; | 6 | import org.springframework.http.MediaType; |
| 7 | +import org.springframework.web.context.request.RequestAttributes; | ||
| 8 | +import org.springframework.web.context.request.RequestContextHolder; | ||
| 9 | +import org.springframework.web.context.request.ServletRequestAttributes; | ||
| 7 | 10 | ||
| 8 | import javax.servlet.http.HttpServletRequest; | 11 | import javax.servlet.http.HttpServletRequest; |
| 9 | import javax.servlet.http.HttpServletResponse; | 12 | import javax.servlet.http.HttpServletResponse; |
| @@ -54,4 +57,33 @@ public class ServletUtils { | @@ -54,4 +57,33 @@ public class ServletUtils { | ||
| 54 | return ua != null ? ua : ""; | 57 | return ua != null ? ua : ""; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| 60 | + /** | ||
| 61 | + * 获得请求 | ||
| 62 | + * | ||
| 63 | + * @return HttpServletRequest | ||
| 64 | + */ | ||
| 65 | + public static HttpServletRequest getRequest() { | ||
| 66 | + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | ||
| 67 | + if (!(requestAttributes instanceof ServletRequestAttributes)) { | ||
| 68 | + return null; | ||
| 69 | + } | ||
| 70 | + return ((ServletRequestAttributes) requestAttributes).getRequest(); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + public static String getUserAgent() { | ||
| 74 | + HttpServletRequest request = getRequest(); | ||
| 75 | + if (request == null) { | ||
| 76 | + return null; | ||
| 77 | + } | ||
| 78 | + return getUserAgent(request); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + public static String getClientIP() { | ||
| 82 | + HttpServletRequest request = getRequest(); | ||
| 83 | + if (request == null) { | ||
| 84 | + return null; | ||
| 85 | + } | ||
| 86 | + return ServletUtil.getClientIP(request); | ||
| 87 | + } | ||
| 88 | + | ||
| 57 | } | 89 | } |