mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	接入登陆日志
This commit is contained in:
		| @@ -1,6 +1,7 @@ | |||||||
| package com.ruoyi.web.controller.monitor; | package com.ruoyi.web.controller.monitor; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||||
| import org.springframework.security.access.prepost.PreAuthorize; | import org.springframework.security.access.prepost.PreAuthorize; | ||||||
| import org.springframework.web.bind.annotation.DeleteMapping; | import org.springframework.web.bind.annotation.DeleteMapping; | ||||||
| @@ -24,15 +25,14 @@ import com.ruoyi.system.service.ISysLogininforService; | |||||||
|  */ |  */ | ||||||
| @RestController | @RestController | ||||||
| @RequestMapping("/monitor/logininfor") | @RequestMapping("/monitor/logininfor") | ||||||
| public class SysLogininforController extends BaseController | public class SysLogininforController extends BaseController { | ||||||
| { |  | ||||||
|     @Autowired |     @Autowired | ||||||
|     private ISysLogininforService logininforService; |     private ISysLogininforService logininforService; | ||||||
|  |  | ||||||
|     @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") |     @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") | ||||||
|     @GetMapping("/list") |     @GetMapping("/list") | ||||||
|     public TableDataInfo list(SysLogininfor logininfor) |     public TableDataInfo list(SysLogininfor logininfor) { | ||||||
|     { |  | ||||||
|         startPage(); |         startPage(); | ||||||
|         List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |         List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); | ||||||
|         return getDataTable(list); |         return getDataTable(list); | ||||||
| @@ -41,8 +41,7 @@ public class SysLogininforController extends BaseController | |||||||
|     @Log(title = "登录日志", businessType = BusinessType.EXPORT) |     @Log(title = "登录日志", businessType = BusinessType.EXPORT) | ||||||
|     @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") |     @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") | ||||||
|     @GetMapping("/export") |     @GetMapping("/export") | ||||||
|     public AjaxResult export(SysLogininfor logininfor) |     public AjaxResult export(SysLogininfor logininfor) { | ||||||
|     { |  | ||||||
|         List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |         List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); | ||||||
|         ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); |         ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); | ||||||
|         return util.exportExcel(list, "登录日志"); |         return util.exportExcel(list, "登录日志"); | ||||||
|   | |||||||
| @@ -24,9 +24,6 @@ import org.aspectj.lang.reflect.MethodSignature; | |||||||
| import org.springframework.core.annotation.AnnotationUtils; | import org.springframework.core.annotation.AnnotationUtils; | ||||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
| import org.springframework.web.bind.annotation.RequestMethod; | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
| import org.springframework.web.context.request.RequestAttributes; |  | ||||||
| import org.springframework.web.context.request.RequestContextHolder; |  | ||||||
| import org.springframework.web.context.request.ServletRequestAttributes; |  | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||||
| @@ -196,11 +193,10 @@ public class OperateLogAspect { | |||||||
|  |  | ||||||
|     private static void fillRequestFields(SysOperateLogCreateReqVO operateLogVO) { |     private static void fillRequestFields(SysOperateLogCreateReqVO operateLogVO) { | ||||||
|         // 获得 Request 对象 |         // 获得 Request 对象 | ||||||
|         RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); |         HttpServletRequest request = ServletUtils.getRequest(); | ||||||
|         if (!(requestAttributes instanceof ServletRequestAttributes)) { |         if (request == null) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); |  | ||||||
|         // 补全请求信息 |         // 补全请求信息 | ||||||
|         operateLogVO.setRequestMethod(request.getMethod()); |         operateLogVO.setRequestMethod(request.getMethod()); | ||||||
|         operateLogVO.setRequestUrl(request.getRequestURI()); |         operateLogVO.setRequestUrl(request.getRequestURI()); | ||||||
|   | |||||||
| @@ -0,0 +1,4 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.controller.logger; | ||||||
|  |  | ||||||
|  | public class SysLoginLogController { | ||||||
|  | } | ||||||
| @@ -15,27 +15,23 @@ import javax.validation.constraints.Size; | |||||||
| @Data | @Data | ||||||
| public class SysLoginLogBaseVO { | public class SysLoginLogBaseVO { | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "日志类型", required = true, example = "1", notes = "参见 SysLoginLogTypeEnum 枚举类") | ||||||
|  |     @NotNull(message = "日志类型不能为空") | ||||||
|  |     private Integer logType; | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") |     @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") | ||||||
|     @NotEmpty(message = "链路追踪编号不能为空") |     @NotEmpty(message = "链路追踪编号不能为空") | ||||||
|     private String traceId; |     private String traceId; | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "用户编号", required = true, example = "1024") |  | ||||||
|     @NotNull(message = "用户编号不能为空") |  | ||||||
|     private Long userId; |  | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "用户账号", required = true, example = "yudao") |     @ApiModelProperty(value = "用户账号", required = true, example = "yudao") | ||||||
|     @NotBlank(message = "用户账号不能为空") |     @NotBlank(message = "用户账号不能为空") | ||||||
|     @Size(max = 30, message = "用户账号长度不能超过30个字符") |     @Size(max = 30, message = "用户账号长度不能超过30个字符") | ||||||
|     private String username; |     private String username; | ||||||
|  |  | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "登陆结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类") |     @ApiModelProperty(value = "登陆结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类") | ||||||
|     @NotNull(message = "登陆结果不能为空") |     @NotNull(message = "登陆结果不能为空") | ||||||
|     private Integer result; |     private Integer result; | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") |  | ||||||
|     private String content; |  | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") |     @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") | ||||||
|     @NotEmpty(message = "用户 IP 不能为空") |     @NotEmpty(message = "用户 IP 不能为空") | ||||||
|     private String userIp; |     private String userIp; | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| package cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog; | package cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog; | ||||||
|  |  | ||||||
| import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO; |  | ||||||
| import io.swagger.annotations.ApiModel; | import io.swagger.annotations.ApiModel; | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||||
| @@ -11,5 +10,5 @@ import lombok.ToString; | |||||||
| @Data | @Data | ||||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||||
| @ToString(callSuper = true) | @ToString(callSuper = true) | ||||||
| public class SysLoginLogCreateReqVO extends SysOperateLogCreateReqVO { | public class SysLoginLogCreateReqVO extends SysLoginLogBaseVO { | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.convert.logger; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO; | ||||||
|  | import org.mapstruct.Mapper; | ||||||
|  | import org.mapstruct.factory.Mappers; | ||||||
|  |  | ||||||
|  | @Mapper | ||||||
|  | public interface SysLoginLogConvert { | ||||||
|  |  | ||||||
|  |     SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class); | ||||||
|  |  | ||||||
|  |     SysLoginLogDO convert(SysLoginLogCreateReqVO bean); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO; | ||||||
|  | import org.apache.ibatis.annotations.Mapper; | ||||||
|  |  | ||||||
|  | @Mapper | ||||||
|  | public interface SysLoginLogMapper extends BaseMapperX<SysLoginLogDO> { | ||||||
|  | } | ||||||
| @@ -1,32 +1,40 @@ | |||||||
| package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; | package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; | ||||||
|  |  | ||||||
| import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | ||||||
| import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; | ||||||
| import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; | ||||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  | import lombok.ToString; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 系统访问记录表 |  * 登陆日志表 | ||||||
|  |  * | ||||||
|  |  * 注意,包括登陆和登出两种行为 | ||||||
|  * |  * | ||||||
|  * @author ruoyi |  * @author ruoyi | ||||||
|  */ |  */ | ||||||
| @TableName("用户登陆日志") | @TableName("sys_login_log") | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | @ToString(callSuper = true) | ||||||
| public class SysLoginLogDO extends BaseDO { | public class SysLoginLogDO extends BaseDO { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 日志主键 |      * 日志主键 | ||||||
|      */ |      */ | ||||||
|     private Long id; |     private Long id; | ||||||
|  |     /** | ||||||
|  |      * 日志类型 | ||||||
|  |      * | ||||||
|  |      * 枚举 {@link SysLoginLogTypeEnum} | ||||||
|  |      */ | ||||||
|  |     private Integer logType; | ||||||
|     /** |     /** | ||||||
|      * 链路追踪编号 |      * 链路追踪编号 | ||||||
|      */ |      */ | ||||||
|     private String traceId; |     private String traceId; | ||||||
|     /** |  | ||||||
|      * 用户编号 |  | ||||||
|      * |  | ||||||
|      * 外键 {@link SysUserDO#getId()} |  | ||||||
|      */ |  | ||||||
|     private Long userId; |  | ||||||
|     /** |     /** | ||||||
|      * 用户账号 |      * 用户账号 | ||||||
|      * |      * | ||||||
| @@ -39,12 +47,10 @@ public class SysLoginLogDO extends BaseDO { | |||||||
|      * 枚举 {@link SysLoginResultEnum} |      * 枚举 {@link SysLoginResultEnum} | ||||||
|      */ |      */ | ||||||
|     private Integer result; |     private Integer result; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 用户 IP |      * 用户 IP | ||||||
|      */ |      */ | ||||||
|     private String userIp; |     private String userIp; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 浏览器 UA |      * 浏览器 UA | ||||||
|      */ |      */ | ||||||
|   | |||||||
| @@ -13,6 +13,8 @@ public interface SysErrorCodeConstants { | |||||||
|     ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); |     ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); | ||||||
|     ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用"); |     ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用"); | ||||||
|     ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登陆失败的兜底,位置原因 |     ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登陆失败的兜底,位置原因 | ||||||
|  |     ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在"); | ||||||
|  |     ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确"); | ||||||
|  |  | ||||||
|     // ========== TOKEN 模块 1002001000 ========== |     // ========== TOKEN 模块 1002001000 ========== | ||||||
|     ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期"); |     ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期"); | ||||||
|   | |||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.enums.logger; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Getter; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登陆日志的类型枚举 | ||||||
|  |  */ | ||||||
|  | @Getter | ||||||
|  | @AllArgsConstructor | ||||||
|  | public enum SysLoginLogTypeEnum { | ||||||
|  |  | ||||||
|  |     LOGIN(1), | ||||||
|  |     LOGOUT(2); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 日志类型 | ||||||
|  |      */ | ||||||
|  |     private final Integer type; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -11,6 +11,12 @@ import lombok.Getter; | |||||||
| public enum SysLoginResultEnum { | public enum SysLoginResultEnum { | ||||||
|  |  | ||||||
|     SUCCESS(0), // 成功 |     SUCCESS(0), // 成功 | ||||||
|  |     BAD_CREDENTIALS(10), // 账号或密码不正确 | ||||||
|  |     USER_DISABLED(20), // 账号或密码不正确 | ||||||
|  |     CAPTCHA_NOT_FOUND(30), // 验证码不存在 | ||||||
|  |     CAPTCHA_CODE_ERROR(31), // 验证码不正确 | ||||||
|  |  | ||||||
|  |     UNKNOWN_ERROR(100), // 未知异常 | ||||||
|     ; |     ; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -3,16 +3,24 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl; | |||||||
| import cn.hutool.core.util.IdUtil; | import cn.hutool.core.util.IdUtil; | ||||||
| import cn.hutool.core.util.StrUtil; | import cn.hutool.core.util.StrUtil; | ||||||
| import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | ||||||
|  | import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; | ||||||
| import cn.iocoder.dashboard.framework.security.config.SecurityProperties; | import cn.iocoder.dashboard.framework.security.config.SecurityProperties; | ||||||
| import cn.iocoder.dashboard.framework.security.core.LoginUser; | import cn.iocoder.dashboard.framework.security.core.LoginUser; | ||||||
|  | import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; | ||||||
|  | import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||||||
| import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; | import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; | ||||||
| import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; | ||||||
| import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; | import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; | ||||||
|  | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; | ||||||
| import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; | ||||||
| import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; | import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; | ||||||
|  | import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; | ||||||
|  | import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService; | ||||||
| import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; | import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; | ||||||
| import cn.iocoder.dashboard.modules.system.service.user.SysUserService; | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; | ||||||
| import cn.iocoder.dashboard.util.date.DateUtils; | import cn.iocoder.dashboard.util.date.DateUtils; | ||||||
|  | import cn.iocoder.dashboard.util.servlet.ServletUtils; | ||||||
| import io.jsonwebtoken.Claims; | import io.jsonwebtoken.Claims; | ||||||
| import io.jsonwebtoken.JwtException; | import io.jsonwebtoken.JwtException; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| @@ -55,6 +63,10 @@ public class SysAuthServiceImpl implements SysAuthService { | |||||||
|     private SysUserService userService; |     private SysUserService userService; | ||||||
|     @Resource |     @Resource | ||||||
|     private SysPermissionService permissionService; |     private SysPermissionService permissionService; | ||||||
|  |     @Resource | ||||||
|  |     private SysCaptchaService captchaService; | ||||||
|  |     @Resource | ||||||
|  |     private SysLoginLogService loginLogService; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private SysLoginUserRedisDAO loginUserRedisDAO; |     private SysLoginUserRedisDAO loginUserRedisDAO; | ||||||
| @@ -87,7 +99,7 @@ public class SysAuthServiceImpl implements SysAuthService { | |||||||
|     @Override |     @Override | ||||||
|     public String login(String username, String password, String captchaUUID, String captchaCode) { |     public String login(String username, String password, String captchaUUID, String captchaCode) { | ||||||
|         // 判断验证码是否正确 |         // 判断验证码是否正确 | ||||||
|         this.verifyCaptcha(captchaUUID, captchaCode); |         this.verifyCaptcha(username, captchaUUID, captchaCode); | ||||||
|  |  | ||||||
|         // 使用账号密码,进行登陆。 |         // 使用账号密码,进行登陆。 | ||||||
|         LoginUser loginUser = this.login0(username, password); |         LoginUser loginUser = this.login0(username, password); | ||||||
| @@ -102,18 +114,20 @@ public class SysAuthServiceImpl implements SysAuthService { | |||||||
|         return tokenService.createToken(sessionId); |         return tokenService.createToken(sessionId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void verifyCaptcha(String captchaUUID, String captchaCode) { |     private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { | ||||||
|         //        String verifyKey = Constants.CAPTCHA_CODE_KEY + captchaUUID; |         String code = captchaService.getCaptchaCode(captchaUUID); | ||||||
| //        String captcha = redisCache.getCacheObject(verifyKey); |         // 验证码不存在 | ||||||
| //        redisCache.deleteObject(verifyKey); |         if (code == null) { | ||||||
| //        if (captcha == null) { |             this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_NOT_FOUND); | ||||||
| //            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); |             throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND); | ||||||
| //            throw new CaptchaExpireException(); |         } | ||||||
| //        } |         // 验证码不正确 | ||||||
| //        if (!code.equalsIgnoreCase(captcha)) { |         if (!code.equals(captchaCode)) { | ||||||
| //            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); |             this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_CODE_ERROR); | ||||||
| //            throw new CaptchaException(); |             throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR); | ||||||
| //        } |         } | ||||||
|  |         // 正确,所以要删除下验证码 | ||||||
|  |         captchaService.deleteCaptchaCode(captchaUUID); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private LoginUser login0(String username, String password) { |     private LoginUser login0(String username, String password) { | ||||||
| @@ -124,22 +138,33 @@ public class SysAuthServiceImpl implements SysAuthService { | |||||||
|             // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 |             // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 | ||||||
|             authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); |             authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); | ||||||
|         } catch (BadCredentialsException badCredentialsException) { |         } catch (BadCredentialsException badCredentialsException) { | ||||||
|             // TODO 日志优化 |             this.createLoginLog(username, SysLoginResultEnum.BAD_CREDENTIALS); | ||||||
| //            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); |  | ||||||
|             throw exception(AUTH_LOGIN_BAD_CREDENTIALS); |             throw exception(AUTH_LOGIN_BAD_CREDENTIALS); | ||||||
|         } catch (DisabledException disabledException) { |         } catch (DisabledException disabledException) { | ||||||
|             // TODO 日志优化 |             this.createLoginLog(username, SysLoginResultEnum.USER_DISABLED); | ||||||
|             throw exception(AUTH_LOGIN_USER_DISABLED); |             throw exception(AUTH_LOGIN_USER_DISABLED); | ||||||
|         } catch (AuthenticationException authenticationException) { |         } catch (AuthenticationException authenticationException) { | ||||||
|             // TODO 日志优化 |             log.error("[login0][username({}) 发生未知异常]", username, authenticationException); | ||||||
|  |             this.createLoginLog(username, SysLoginResultEnum.UNKNOWN_ERROR); | ||||||
|             throw exception(AUTH_LOGIN_FAIL_UNKNOWN); |             throw exception(AUTH_LOGIN_FAIL_UNKNOWN); | ||||||
|         } |         } | ||||||
|         // TODO 需要优化 |         // 登陆成功 | ||||||
| //        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); |  | ||||||
|         Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); |         Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); | ||||||
|  |         this.createLoginLog(username, SysLoginResultEnum.SUCCESS); | ||||||
|         return (LoginUser) authentication.getPrincipal(); |         return (LoginUser) authentication.getPrincipal(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private void createLoginLog(String username, SysLoginResultEnum loginResult) { | ||||||
|  |         SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO(); | ||||||
|  |         reqVO.setLogType(SysLoginLogTypeEnum.LOGIN.getType()); | ||||||
|  |         reqVO.setTraceId(TracerUtils.getTraceId()); | ||||||
|  |         reqVO.setUsername(username); | ||||||
|  |         reqVO.setUserAgent(ServletUtils.getUserAgent()); | ||||||
|  |         reqVO.setUserIp(ServletUtils.getClientIP()); | ||||||
|  |         reqVO.setResult(loginResult.getResult()); | ||||||
|  |         loginLogService.createLoginLog(reqVO); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获得 User 拥有的角色编号数组 |      * 获得 User 拥有的角色编号数组 | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -7,6 +7,26 @@ import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageR | |||||||
|  */ |  */ | ||||||
| public interface SysCaptchaService { | public interface SysCaptchaService { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得验证码图片 | ||||||
|  |      * | ||||||
|  |      * @return 验证码图片 | ||||||
|  |      */ | ||||||
|     SysCaptchaImageRespVO getCaptchaImage(); |     SysCaptchaImageRespVO getCaptchaImage(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得 uuid 对应的验证码 | ||||||
|  |      * | ||||||
|  |      * @param uuid 验证码编号 | ||||||
|  |      * @return 验证码 | ||||||
|  |      */ | ||||||
|  |     String getCaptchaCode(String uuid); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除 uuid 对应的验证码 | ||||||
|  |      * | ||||||
|  |      * @param uuid 验证码编号 | ||||||
|  |      */ | ||||||
|  |     void deleteCaptchaCode(String uuid); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,4 +35,14 @@ public class SysCaptchaServiceImpl implements SysCaptchaService { | |||||||
|         return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); |         return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String getCaptchaCode(String uuid) { | ||||||
|  |         return captchaRedisDAO.get(uuid); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void deleteCaptchaCode(String uuid) { | ||||||
|  |         captchaRedisDAO.delete(uuid); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,17 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.service.logger; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登陆日志 Service 接口 | ||||||
|  |  */ | ||||||
|  | public interface SysLoginLogService { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建登陆日志 | ||||||
|  |      * | ||||||
|  |      * @param reqVO 日志信息 | ||||||
|  |      */ | ||||||
|  |     void createLoginLog(SysLoginLogCreateReqVO reqVO); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.service.logger.impl; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.convert.logger.SysLoginLogConvert; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysLoginLogMapper; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | import javax.annotation.Resource; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登陆日志 Service 实现 | ||||||
|  |  */ | ||||||
|  | @Service | ||||||
|  | public class SysLoginLogServiceImpl implements SysLoginLogService { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private SysLoginLogMapper loginLogMapper; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void createLoginLog(SysLoginLogCreateReqVO reqVO) { | ||||||
|  |         SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqVO); | ||||||
|  |         loginLogMapper.insert(loginLog); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -4,6 +4,9 @@ import cn.hutool.core.io.IoUtil; | |||||||
| import cn.hutool.extra.servlet.ServletUtil; | import cn.hutool.extra.servlet.ServletUtil; | ||||||
| import com.alibaba.fastjson.JSON; | import com.alibaba.fastjson.JSON; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
|  | import org.springframework.web.context.request.RequestAttributes; | ||||||
|  | import org.springframework.web.context.request.RequestContextHolder; | ||||||
|  | import org.springframework.web.context.request.ServletRequestAttributes; | ||||||
|  |  | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||||
| @@ -54,4 +57,33 @@ public class ServletUtils { | |||||||
|         return ua != null ? ua : ""; |         return ua != null ? ua : ""; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得请求 | ||||||
|  |      * | ||||||
|  |      * @return HttpServletRequest | ||||||
|  |      */ | ||||||
|  |     public static HttpServletRequest getRequest() { | ||||||
|  |         RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | ||||||
|  |         if (!(requestAttributes instanceof ServletRequestAttributes)) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         return ((ServletRequestAttributes) requestAttributes).getRequest(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static String getUserAgent() { | ||||||
|  |         HttpServletRequest request = getRequest(); | ||||||
|  |         if (request == null) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         return getUserAgent(request); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static String getClientIP() { | ||||||
|  |         HttpServletRequest request = getRequest(); | ||||||
|  |         if (request == null) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         return ServletUtil.getClientIP(request); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV