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 | 1 | package com.ruoyi.web.controller.monitor; |
| 2 | 2 | |
| 3 | 3 | import java.util.List; |
| 4 | + | |
| 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; |
| 5 | 6 | import org.springframework.security.access.prepost.PreAuthorize; |
| 6 | 7 | import org.springframework.web.bind.annotation.DeleteMapping; |
| ... | ... | @@ -24,15 +25,14 @@ import com.ruoyi.system.service.ISysLogininforService; |
| 24 | 25 | */ |
| 25 | 26 | @RestController |
| 26 | 27 | @RequestMapping("/monitor/logininfor") |
| 27 | -public class SysLogininforController extends BaseController | |
| 28 | -{ | |
| 28 | +public class SysLogininforController extends BaseController { | |
| 29 | + | |
| 29 | 30 | @Autowired |
| 30 | 31 | private ISysLogininforService logininforService; |
| 31 | 32 | |
| 32 | 33 | @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") |
| 33 | 34 | @GetMapping("/list") |
| 34 | - public TableDataInfo list(SysLogininfor logininfor) | |
| 35 | - { | |
| 35 | + public TableDataInfo list(SysLogininfor logininfor) { | |
| 36 | 36 | startPage(); |
| 37 | 37 | List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |
| 38 | 38 | return getDataTable(list); |
| ... | ... | @@ -41,8 +41,7 @@ public class SysLogininforController extends BaseController |
| 41 | 41 | @Log(title = "登录日志", businessType = BusinessType.EXPORT) |
| 42 | 42 | @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") |
| 43 | 43 | @GetMapping("/export") |
| 44 | - public AjaxResult export(SysLogininfor logininfor) | |
| 45 | - { | |
| 44 | + public AjaxResult export(SysLogininfor logininfor) { | |
| 46 | 45 | List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |
| 47 | 46 | ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); |
| 48 | 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 | 24 | import org.springframework.core.annotation.AnnotationUtils; |
| 25 | 25 | import org.springframework.web.bind.annotation.RequestMapping; |
| 26 | 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 | 27 | import org.springframework.web.multipart.MultipartFile; |
| 31 | 28 | |
| 32 | 29 | import javax.annotation.Resource; |
| ... | ... | @@ -196,11 +193,10 @@ public class OperateLogAspect { |
| 196 | 193 | |
| 197 | 194 | private static void fillRequestFields(SysOperateLogCreateReqVO operateLogVO) { |
| 198 | 195 | // 获得 Request 对象 |
| 199 | - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | |
| 200 | - if (!(requestAttributes instanceof ServletRequestAttributes)) { | |
| 196 | + HttpServletRequest request = ServletUtils.getRequest(); | |
| 197 | + if (request == null) { | |
| 201 | 198 | return; |
| 202 | 199 | } |
| 203 | - HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); | |
| 204 | 200 | // 补全请求信息 |
| 205 | 201 | operateLogVO.setRequestMethod(request.getMethod()); |
| 206 | 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 | 15 | @Data |
| 16 | 16 | public class SysLoginLogBaseVO { |
| 17 | 17 | |
| 18 | + @ApiModelProperty(value = "日志类型", required = true, example = "1", notes = "参见 SysLoginLogTypeEnum 枚举类") | |
| 19 | + @NotNull(message = "日志类型不能为空") | |
| 20 | + private Integer logType; | |
| 21 | + | |
| 18 | 22 | @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") |
| 19 | 23 | @NotEmpty(message = "链路追踪编号不能为空") |
| 20 | 24 | private String traceId; |
| 21 | 25 | |
| 22 | - @ApiModelProperty(value = "用户编号", required = true, example = "1024") | |
| 23 | - @NotNull(message = "用户编号不能为空") | |
| 24 | - private Long userId; | |
| 25 | - | |
| 26 | 26 | @ApiModelProperty(value = "用户账号", required = true, example = "yudao") |
| 27 | 27 | @NotBlank(message = "用户账号不能为空") |
| 28 | 28 | @Size(max = 30, message = "用户账号长度不能超过30个字符") |
| 29 | 29 | private String username; |
| 30 | 30 | |
| 31 | - | |
| 32 | 31 | @ApiModelProperty(value = "登陆结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类") |
| 33 | 32 | @NotNull(message = "登陆结果不能为空") |
| 34 | 33 | private Integer result; |
| 35 | 34 | |
| 36 | - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") | |
| 37 | - private String content; | |
| 38 | - | |
| 39 | 35 | @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") |
| 40 | 36 | @NotEmpty(message = "用户 IP 不能为空") |
| 41 | 37 | private String userIp; | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogCreateReqVO.java
| 1 | 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 | 3 | import io.swagger.annotations.ApiModel; |
| 5 | 4 | import lombok.Data; |
| 6 | 5 | import lombok.EqualsAndHashCode; |
| ... | ... | @@ -11,5 +10,5 @@ import lombok.ToString; |
| 11 | 10 | @Data |
| 12 | 11 | @EqualsAndHashCode(callSuper = true) |
| 13 | 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 | 1 | package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; |
| 2 | 2 | |
| 3 | 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 | 5 | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; |
| 6 | 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 | 16 | * @author ruoyi |
| 12 | 17 | */ |
| 13 | -@TableName("用户登陆日志") | |
| 18 | +@TableName("sys_login_log") | |
| 19 | +@Data | |
| 20 | +@EqualsAndHashCode(callSuper = true) | |
| 21 | +@ToString(callSuper = true) | |
| 14 | 22 | public class SysLoginLogDO extends BaseDO { |
| 15 | 23 | |
| 16 | 24 | /** |
| ... | ... | @@ -18,15 +26,15 @@ public class SysLoginLogDO extends BaseDO { |
| 18 | 26 | */ |
| 19 | 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 | 47 | * 枚举 {@link SysLoginResultEnum} |
| 40 | 48 | */ |
| 41 | 49 | private Integer result; |
| 42 | - | |
| 43 | 50 | /** |
| 44 | 51 | * 用户 IP |
| 45 | 52 | */ |
| 46 | 53 | private String userIp; |
| 47 | - | |
| 48 | 54 | /** |
| 49 | 55 | * 浏览器 UA |
| 50 | 56 | */ | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
| ... | ... | @@ -13,6 +13,8 @@ public interface SysErrorCodeConstants { |
| 13 | 13 | ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); |
| 14 | 14 | ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用"); |
| 15 | 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 | 19 | // ========== TOKEN 模块 1002001000 ========== |
| 18 | 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 | 11 | public enum SysLoginResultEnum { |
| 12 | 12 | |
| 13 | 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 | 3 | import cn.hutool.core.util.IdUtil; |
| 4 | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | 5 | import cn.iocoder.dashboard.common.enums.CommonStatusEnum; |
| 6 | +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; | |
| 6 | 7 | import cn.iocoder.dashboard.framework.security.config.SecurityProperties; |
| 7 | 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 | 11 | import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; |
| 9 | 12 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 10 | 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 | 16 | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; |
| 12 | 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 | 20 | import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; |
| 14 | 21 | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; |
| 15 | 22 | import cn.iocoder.dashboard.util.date.DateUtils; |
| 23 | +import cn.iocoder.dashboard.util.servlet.ServletUtils; | |
| 16 | 24 | import io.jsonwebtoken.Claims; |
| 17 | 25 | import io.jsonwebtoken.JwtException; |
| 18 | 26 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -55,6 +63,10 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 55 | 63 | private SysUserService userService; |
| 56 | 64 | @Resource |
| 57 | 65 | private SysPermissionService permissionService; |
| 66 | + @Resource | |
| 67 | + private SysCaptchaService captchaService; | |
| 68 | + @Resource | |
| 69 | + private SysLoginLogService loginLogService; | |
| 58 | 70 | |
| 59 | 71 | @Resource |
| 60 | 72 | private SysLoginUserRedisDAO loginUserRedisDAO; |
| ... | ... | @@ -87,7 +99,7 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 87 | 99 | @Override |
| 88 | 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 | 105 | LoginUser loginUser = this.login0(username, password); |
| ... | ... | @@ -102,18 +114,20 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 102 | 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 | 133 | private LoginUser login0(String username, String password) { |
| ... | ... | @@ -124,22 +138,33 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 124 | 138 | // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 |
| 125 | 139 | authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); |
| 126 | 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 | 142 | throw exception(AUTH_LOGIN_BAD_CREDENTIALS); |
| 130 | 143 | } catch (DisabledException disabledException) { |
| 131 | - // TODO 日志优化 | |
| 144 | + this.createLoginLog(username, SysLoginResultEnum.USER_DISABLED); | |
| 132 | 145 | throw exception(AUTH_LOGIN_USER_DISABLED); |
| 133 | 146 | } catch (AuthenticationException authenticationException) { |
| 134 | - // TODO 日志优化 | |
| 147 | + log.error("[login0][username({}) 发生未知异常]", username, authenticationException); | |
| 148 | + this.createLoginLog(username, SysLoginResultEnum.UNKNOWN_ERROR); | |
| 135 | 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 | 152 | Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); |
| 153 | + this.createLoginLog(username, SysLoginResultEnum.SUCCESS); | |
| 140 | 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 | 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 | 7 | */ |
| 8 | 8 | public interface SysCaptchaService { |
| 9 | 9 | |
| 10 | + /** | |
| 11 | + * 获得验证码图片 | |
| 12 | + * | |
| 13 | + * @return 验证码图片 | |
| 14 | + */ | |
| 10 | 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 | 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 | 4 | import cn.hutool.extra.servlet.ServletUtil; |
| 5 | 5 | import com.alibaba.fastjson.JSON; |
| 6 | 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 | 11 | import javax.servlet.http.HttpServletRequest; |
| 9 | 12 | import javax.servlet.http.HttpServletResponse; |
| ... | ... | @@ -54,4 +57,33 @@ public class ServletUtils { |
| 54 | 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 | } | ... | ... |