Commit e999cc31c6890e137c76c56a9b5946dd35a230c0

Authored by YunaiV
1 parent 28fdc8e4

初始化 c 端的登录逻辑

Showing 36 changed files with 612 additions and 96 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogCreateReqVO.java deleted
1 -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog;  
2 -  
3 -import io.swagger.annotations.ApiModel;  
4 -import io.swagger.annotations.ApiModelProperty;  
5 -import lombok.Data;  
6 -import lombok.EqualsAndHashCode;  
7 -import lombok.ToString;  
8 -  
9 -@ApiModel(value = "登录日志创建 Request VO",  
10 - description = "暂时提供给前端,仅仅后端记录登录日志时,进行使用")  
11 -@Data  
12 -@EqualsAndHashCode(callSuper = true)  
13 -@ToString(callSuper = true)  
14 -public class SysLoginLogCreateReqVO extends SysLoginLogBaseVO {  
15 -  
16 - @ApiModelProperty(value = "用户编号", example = "1")  
17 - private Long userId;  
18 -  
19 -}  
20 \ No newline at end of file 0 \ No newline at end of file
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysLoginLogConvert.java
1 package cn.iocoder.yudao.adminserver.modules.system.convert.logger; 1 package cn.iocoder.yudao.adminserver.modules.system.convert.logger;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;  
5 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO; 5 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogRespVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogRespVO;
7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
@@ -15,7 +15,7 @@ public interface SysLoginLogConvert { @@ -15,7 +15,7 @@ public interface SysLoginLogConvert {
15 15
16 SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class); 16 SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class);
17 17
18 - SysLoginLogDO convert(SysLoginLogCreateReqVO bean); 18 + SysLoginLogDO convert(SysLoginLogCreateReqDTO bean);
19 19
20 PageResult<SysLoginLogRespVO> convertPage(PageResult<SysLoginLogDO> page); 20 PageResult<SysLoginLogRespVO> convertPage(PageResult<SysLoginLogDO> page);
21 21
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/auth/SysUserSessionDO.java
@@ -38,6 +38,12 @@ public class SysUserSessionDO extends BaseDO { @@ -38,6 +38,12 @@ public class SysUserSessionDO extends BaseDO {
38 * 关联 {@link SysUserDO#getId()} 38 * 关联 {@link SysUserDO#getId()}
39 */ 39 */
40 private Long userId; 40 private Long userId;
  41 + /**
  42 + * 用户类型
  43 + *
  44 + * 枚举 {@link UserTypeEnum}
  45 + */
  46 + private Integer userType;
41 47
42 /** 48 /**
43 * 用户账号 49 * 用户账号
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysLoginLogDO.java
@@ -14,7 +14,7 @@ import lombok.ToString; @@ -14,7 +14,7 @@ import lombok.ToString;
14 * 14 *
15 * 注意,包括登录和登出两种行为 15 * 注意,包括登录和登出两种行为
16 * 16 *
17 - * @author ruoyi 17 + * @author 芋道源码
18 */ 18 */
19 @TableName("sys_login_log") 19 @TableName("sys_login_log")
20 @Data 20 @Data
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
1 package cn.iocoder.yudao.adminserver.modules.system.enums; 1 package cn.iocoder.yudao.adminserver.modules.system.enums;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.config.ErrorCodeConfiguration;  
4 import cn.iocoder.yudao.framework.common.exception.ErrorCode; 3 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
5 -import org.springframework.validation.Errors;  
6 4
7 /** 5 /**
8 * System 错误码枚举类 6 * System 错误码枚举类
@@ -14,7 +12,7 @@ public interface SysErrorCodeConstants { @@ -14,7 +12,7 @@ public interface SysErrorCodeConstants {
14 // ========== AUTH 模块 1002000000 ========== 12 // ========== AUTH 模块 1002000000 ==========
15 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); 13 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
16 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用"); 14 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
17 - ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登录失败的兜底,位置原因 15 + ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登录失败的兜底,未知原因
18 ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在"); 16 ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在");
19 ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确"); 17 ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确");
20 ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定"); 18 ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java
@@ -13,6 +13,8 @@ public enum SysLoginLogTypeEnum { @@ -13,6 +13,8 @@ public enum SysLoginLogTypeEnum {
13 LOGIN_USERNAME(100), // 使用账号登录 13 LOGIN_USERNAME(100), // 使用账号登录
14 LOGIN_SOCIAL(101), // 使用社交登录 14 LOGIN_SOCIAL(101), // 使用社交登录
15 LOGIN_MOCK(102), // 使用 Mock 登录 15 LOGIN_MOCK(102), // 使用 Mock 登录
  16 + LOGIN_MOBILE(103), // 使用手机登陆
  17 + LOGIN_SMS(104), // 使用短信登陆
16 18
17 LOGOUT_SELF(200), // 自己主动登出 19 LOGOUT_SELF(200), // 自己主动登出
18 LOGOUT_TIMEOUT(201), // 超时登出 20 LOGOUT_TIMEOUT(201), // 超时登出
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginResultEnum.java
@@ -13,8 +13,8 @@ public enum SysLoginResultEnum { @@ -13,8 +13,8 @@ public enum SysLoginResultEnum {
13 SUCCESS(0), // 成功 13 SUCCESS(0), // 成功
14 BAD_CREDENTIALS(10), // 账号或密码不正确 14 BAD_CREDENTIALS(10), // 账号或密码不正确
15 USER_DISABLED(20), // 用户被禁用 15 USER_DISABLED(20), // 用户被禁用
16 - CAPTCHA_NOT_FOUND(30), // 验证码不存在  
17 - CAPTCHA_CODE_ERROR(31), // 验证码不正确 16 + CAPTCHA_NOT_FOUND(30), // 图片验证码不存在
  17 + CAPTCHA_CODE_ERROR(31), // 图片验证码不正确
18 18
19 UNKNOWN_ERROR(100), // 未知异常 19 UNKNOWN_ERROR(100), // 未知异常
20 ; 20 ;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java
@@ -46,13 +46,6 @@ public interface SysUserSessionService { @@ -46,13 +46,6 @@ public interface SysUserSessionService {
46 LoginUser getLoginUser(String sessionId); 46 LoginUser getLoginUser(String sessionId);
47 47
48 /** 48 /**
49 - * 获取当前登录用户信息  
50 - * @param username 用户名称  
51 - * @return 在线用户  
52 - */  
53 - String getSessionId(String username);  
54 -  
55 - /**  
56 * 获得 Session 超时时间,单位:毫秒 49 * 获得 Session 超时时间,单位:毫秒
57 * 50 *
58 * @return 超时时间 51 * @return 超时时间
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAu @@ -5,7 +5,6 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAu
5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO; 5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
7 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO; 7 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
8 -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;  
9 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; 8 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO; 9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
@@ -15,6 +14,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; @@ -15,6 +14,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
15 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
16 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; 15 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
17 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; 16 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
  17 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
18 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 18 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
19 import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService; 19 import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
20 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 20 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
@@ -158,20 +158,20 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -158,20 +158,20 @@ public class SysAuthServiceImpl implements SysAuthService {
158 // 获得用户 158 // 获得用户
159 SysUserDO user = userService.getUserByUsername(username); 159 SysUserDO user = userService.getUserByUsername(username);
160 // 插入登录日志 160 // 插入登录日志
161 - SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO();  
162 - reqVO.setLogType(logTypeEnum.getType());  
163 - reqVO.setTraceId(TracerUtils.getTraceId()); 161 + SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
  162 + reqDTO.setLogType(logTypeEnum.getType());
  163 + reqDTO.setTraceId(TracerUtils.getTraceId());
164 if (user != null) { 164 if (user != null) {
165 - reqVO.setUserId(user.getId()); 165 + reqDTO.setUserId(user.getId());
166 } 166 }
167 - reqVO.setUsername(username);  
168 - reqVO.setUserAgent(ServletUtils.getUserAgent());  
169 - reqVO.setUserIp(ServletUtils.getClientIP());  
170 - reqVO.setResult(loginResult.getResult());  
171 - loginLogService.createLoginLog(reqVO); 167 + reqDTO.setUsername(username);
  168 + reqDTO.setUserAgent(ServletUtils.getUserAgent());
  169 + reqDTO.setUserIp(ServletUtils.getClientIP());
  170 + reqDTO.setResult(loginResult.getResult());
  171 + loginLogService.createLoginLog(reqDTO);
172 // 更新最后登录时间 172 // 更新最后登录时间
173 if (user != null && Objects.equals(SysLoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { 173 if (user != null && Objects.equals(SysLoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
174 - 174 + userService.updateUserLogin(user.getId(), ServletUtils.getClientIP());
175 } 175 }
176 } 176 }
177 177
@@ -258,14 +258,14 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -258,14 +258,14 @@ public class SysAuthServiceImpl implements SysAuthService {
258 } 258 }
259 259
260 private void createLogoutLog(String username) { 260 private void createLogoutLog(String username) {
261 - SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO();  
262 - reqVO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());  
263 - reqVO.setTraceId(TracerUtils.getTraceId());  
264 - reqVO.setUsername(username);  
265 - reqVO.setUserAgent(ServletUtils.getUserAgent());  
266 - reqVO.setUserIp(ServletUtils.getClientIP());  
267 - reqVO.setResult(SysLoginResultEnum.SUCCESS.getResult());  
268 - loginLogService.createLoginLog(reqVO); 261 + SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
  262 + reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
  263 + reqDTO.setTraceId(TracerUtils.getTraceId());
  264 + reqDTO.setUsername(username);
  265 + reqDTO.setUserAgent(ServletUtils.getUserAgent());
  266 + reqDTO.setUserIp(ServletUtils.getClientIP());
  267 + reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult());
  268 + loginLogService.createLoginLog(reqDTO);
269 } 269 }
270 270
271 @Override 271 @Override
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java
@@ -3,12 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; @@ -3,12 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.IdUtil; 4 import cn.hutool.core.util.IdUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
7 -import cn.iocoder.yudao.framework.security.config.SecurityProperties;  
8 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
9 -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;  
10 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
11 -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;  
12 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO;
13 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
14 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper; 9 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper;
@@ -17,10 +12,13 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeE @@ -17,10 +12,13 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeE
17 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; 12 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
18 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
19 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
  15 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
20 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 16 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
21 -import com.baomidou.mybatisplus.core.conditions.Wrapper;  
22 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  
23 -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 17 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  18 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  19 +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
  20 +import cn.iocoder.yudao.framework.security.config.SecurityProperties;
  21 +import cn.iocoder.yudao.framework.security.core.LoginUser;
24 import com.google.common.collect.Lists; 22 import com.google.common.collect.Lists;
25 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
26 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
@@ -62,7 +60,8 @@ public class SysUserSessionServiceImpl implements SysUserSessionService { @@ -62,7 +60,8 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
62 loginUserRedisDAO.set(sessionId, loginUser); 60 loginUserRedisDAO.set(sessionId, loginUser);
63 // 写入 DB 中 61 // 写入 DB 中
64 SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId) 62 SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)
65 - .userId(loginUser.getId()).userIp(userIp).userAgent(userAgent).username(loginUser.getUsername()) 63 + .userId(loginUser.getId()).userType(UserTypeEnum.ADMIN.getValue())
  64 + .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())
66 .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis()))) 65 .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())))
67 .build(); 66 .build();
68 userSessionMapper.insert(userSession); 67 userSessionMapper.insert(userSession);
@@ -97,15 +96,6 @@ public class SysUserSessionServiceImpl implements SysUserSessionService { @@ -97,15 +96,6 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
97 } 96 }
98 97
99 @Override 98 @Override
100 - public String getSessionId(String username) {  
101 - QueryWrapper<SysUserSessionDO> wrapper = new QueryWrapper<>();  
102 - wrapper.eq("username", username);  
103 - wrapper.orderByDesc("create_time");  
104 - SysUserSessionDO sysUserSessionDO = userSessionMapper.selectOne(wrapper);  
105 - return sysUserSessionDO.getId();  
106 - }  
107 -  
108 - @Override  
109 public Long getSessionTimeoutMillis() { 99 public Long getSessionTimeoutMillis() {
110 return securityProperties.getSessionTimeout().toMillis(); 100 return securityProperties.getSessionTimeout().toMillis();
111 } 101 }
@@ -142,14 +132,14 @@ public class SysUserSessionServiceImpl implements SysUserSessionService { @@ -142,14 +132,14 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
142 132
143 private void createTimeoutLogoutLog(Collection<SysUserSessionDO> timeoutSessionDOS) { 133 private void createTimeoutLogoutLog(Collection<SysUserSessionDO> timeoutSessionDOS) {
144 for (SysUserSessionDO timeoutSessionDO : timeoutSessionDOS) { 134 for (SysUserSessionDO timeoutSessionDO : timeoutSessionDOS) {
145 - SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO();  
146 - reqVO.setLogType(SysLoginLogTypeEnum.LOGOUT_TIMEOUT.getType());  
147 - reqVO.setTraceId(TracerUtils.getTraceId());  
148 - reqVO.setUsername(timeoutSessionDO.getUsername());  
149 - reqVO.setUserAgent(timeoutSessionDO.getUserAgent());  
150 - reqVO.setUserIp(timeoutSessionDO.getUserIp());  
151 - reqVO.setResult(SysLoginResultEnum.SUCCESS.getResult());  
152 - loginLogService.createLoginLog(reqVO); 135 + SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
  136 + reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_TIMEOUT.getType());
  137 + reqDTO.setTraceId(TracerUtils.getTraceId());
  138 + reqDTO.setUsername(timeoutSessionDO.getUsername());
  139 + reqDTO.setUserAgent(timeoutSessionDO.getUserAgent());
  140 + reqDTO.setUserIp(timeoutSessionDO.getUserIp());
  141 + reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult());
  142 + loginLogService.createLoginLog(reqDTO);
153 } 143 }
154 } 144 }
155 145
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogService.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.logger; 1 package cn.iocoder.yudao.adminserver.modules.system.service.logger;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;  
5 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; 5 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
@@ -16,9 +16,9 @@ public interface SysLoginLogService { @@ -16,9 +16,9 @@ public interface SysLoginLogService {
16 /** 16 /**
17 * 创建登录日志 17 * 创建登录日志
18 * 18 *
19 - * @param reqVO 日志信息 19 + * @param reqDTO 日志信息
20 */ 20 */
21 - void createLoginLog(SysLoginLogCreateReqVO reqVO); 21 + void createLoginLog(SysLoginLogCreateReqDTO reqDTO);
22 22
23 /** 23 /**
24 * 获得登录日志分页 24 * 获得登录日志分页
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/dto/SysLoginLogCreateReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.system.service.logger.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotBlank;
  6 +import javax.validation.constraints.NotEmpty;
  7 +import javax.validation.constraints.NotNull;
  8 +import javax.validation.constraints.Size;
  9 +
  10 +/**
  11 + * 登录日志创建 Request DTO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Data
  16 +public class SysLoginLogCreateReqDTO {
  17 +
  18 + /**
  19 + * 日志类型
  20 + */
  21 + @NotNull(message = "日志类型不能为空")
  22 + private Integer logType;
  23 + /**
  24 + * 链路追踪编号
  25 + */
  26 + @NotEmpty(message = "链路追踪编号不能为空")
  27 + private String traceId;
  28 +
  29 + /**
  30 + * 用户编号
  31 + */
  32 + private Long userId;
  33 + /**
  34 + * 用户账号
  35 + */
  36 + @NotBlank(message = "用户账号不能为空")
  37 + @Size(max = 30, message = "用户账号长度不能超过30个字符")
  38 + private String username;
  39 +
  40 + /**
  41 + * 登录结果
  42 + */
  43 + @NotNull(message = "登录结果不能为空")
  44 + private Integer result;
  45 +
  46 + /**
  47 + * 用户 IP
  48 + */
  49 + @NotEmpty(message = "用户 IP 不能为空")
  50 + private String userIp;
  51 + /**
  52 + * 浏览器 UserAgent
  53 + */
  54 + @NotEmpty(message = "浏览器 UserAgent 不能为空")
  55 + private String userAgent;
  56 +
  57 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.logger.impl; 1 package cn.iocoder.yudao.adminserver.modules.system.service.logger.impl;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;  
4 -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;  
5 -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;  
6 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
7 -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;  
8 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; 3 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
9 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; 4 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
10 import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysLoginLogConvert; 5 import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysLoginLogConvert;
11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO; 6 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
12 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysLoginLogMapper; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysLoginLogMapper;
13 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; 8 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
  9 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  10 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  11 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
14 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
15 13
16 import javax.annotation.Resource; 14 import javax.annotation.Resource;
@@ -26,8 +24,8 @@ public class SysLoginLogServiceImpl implements SysLoginLogService { @@ -26,8 +24,8 @@ public class SysLoginLogServiceImpl implements SysLoginLogService {
26 private SysLoginLogMapper loginLogMapper; 24 private SysLoginLogMapper loginLogMapper;
27 25
28 @Override 26 @Override
29 - public void createLoginLog(SysLoginLogCreateReqVO reqVO) {  
30 - SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqVO); 27 + public void createLoginLog(SysLoginLogCreateReqDTO reqDTO) {
  28 + SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqDTO);
31 loginLog.setUserType(UserTypeEnum.ADMIN.getValue()); 29 loginLog.setUserType(UserTypeEnum.ADMIN.getValue());
32 // 插入 30 // 插入
33 loginLogMapper.insert(loginLog); 31 loginLogMapper.insert(loginLog);
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java
@@ -42,6 +42,14 @@ public interface SysUserService { @@ -42,6 +42,14 @@ public interface SysUserService {
42 void updateUser(SysUserUpdateReqVO reqVO); 42 void updateUser(SysUserUpdateReqVO reqVO);
43 43
44 /** 44 /**
  45 + * 更新用户的最后登陆信息
  46 + *
  47 + * @param id 用户编号
  48 + * @param loginIp 登陆 IP
  49 + */
  50 + void updateUserLogin(Long id, String loginIp);
  51 +
  52 + /**
45 * 修改用户个人信息 53 * 修改用户个人信息
46 * 54 *
47 * @param id 用户编号 55 * @param id 用户编号
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java
@@ -85,6 +85,11 @@ public class SysUserServiceImpl implements SysUserService { @@ -85,6 +85,11 @@ public class SysUserServiceImpl implements SysUserService {
85 } 85 }
86 86
87 @Override 87 @Override
  88 + public void updateUserLogin(Long id, String loginIp) {
  89 + userMapper.updateById(new SysUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date()));
  90 + }
  91 +
  92 + @Override
88 public void updateUserProfile(Long id, SysUserProfileUpdateReqVO reqVO) { 93 public void updateUserProfile(Long id, SysUserProfileUpdateReqVO reqVO) {
89 // 校验正确性 94 // 校验正确性
90 this.checkUserExists(id); 95 this.checkUserExists(id);
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java
@@ -2,9 +2,9 @@ package cn.iocoder.yudao.adminserver.modules.system.service.logger; @@ -2,9 +2,9 @@ package cn.iocoder.yudao.adminserver.modules.system.service.logger;
2 2
3 import cn.hutool.core.util.RandomUtil; 3 import cn.hutool.core.util.RandomUtil;
4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest; 4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
  5 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 7 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
7 -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;  
8 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; 8 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
9 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; 9 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO; 10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
@@ -36,7 +36,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { @@ -36,7 +36,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
36 @Test 36 @Test
37 public void testCreateLoginLog() { 37 public void testCreateLoginLog() {
38 String traceId = TracerUtils.getTraceId(); 38 String traceId = TracerUtils.getTraceId();
39 - SysLoginLogCreateReqVO reqVO = RandomUtils.randomPojo(SysLoginLogCreateReqVO.class, vo -> { 39 + SysLoginLogCreateReqDTO reqDTO = RandomUtils.randomPojo(SysLoginLogCreateReqDTO.class, vo -> {
40 // 指定随机的范围,避免超出范围入库失败 40 // 指定随机的范围,避免超出范围入库失败
41 vo.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); 41 vo.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
42 vo.setResult(RandomUtil.randomEle(SysLoginResultEnum.values()).getResult()); 42 vo.setResult(RandomUtil.randomEle(SysLoginResultEnum.values()).getResult());
@@ -45,11 +45,11 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { @@ -45,11 +45,11 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
45 }); 45 });
46 46
47 // 执行service方法 47 // 执行service方法
48 - sysLoginLogService.createLoginLog(reqVO); 48 + sysLoginLogService.createLoginLog(reqDTO);
49 49
50 // 断言,忽略基本字段 50 // 断言,忽略基本字段
51 SysLoginLogDO sysLoginLogDO = loginLogMapper.selectOne(null); 51 SysLoginLogDO sysLoginLogDO = loginLogMapper.selectOne(null);
52 - assertPojoEquals(reqVO, sysLoginLogDO); 52 + assertPojoEquals(reqDTO, sysLoginLogDO);
53 } 53 }
54 54
55 55
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/convert/package-info.java
1 -package cn.iocoder.yudao.userserver.modules.member.convert;  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +/**
  3 + * 提供 POJO 类的实体转换
  4 + *
  5 + * 目前使用 MapStruct 框架
  6 + */
  7 +package cn.iocoder.yudao.userserver.modules.member.convert;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/enums/MbrErrorCodeConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.member.enums;
  2 +
  3 +import cn.iocoder.yudao.framework.common.exception.ErrorCode;
  4 +
  5 +/**
  6 + * Member 错误码枚举类
  7 + *
  8 + * member 系统,使用 1-004-000-000 段
  9 + */
  10 +public interface MbrErrorCodeConstants {
  11 +
  12 + // ========== AUTH 模块 1004000000 ==========
  13 + ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004000000, "登录失败,账号密码不正确");
  14 + ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1004000001, "登录失败,账号被禁用");
  15 + ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1004000002, "登录失败"); // 登录失败的兜底,未知原因
  16 +
  17 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/auth/impl/MbrAuthServiceImpl.java
1 package cn.iocoder.yudao.userserver.modules.member.service.auth.impl; 1 package cn.iocoder.yudao.userserver.modules.member.service.auth.impl;
2 2
  3 +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
  4 +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
3 import cn.iocoder.yudao.framework.security.core.LoginUser; 5 import cn.iocoder.yudao.framework.security.core.LoginUser;
4 import cn.iocoder.yudao.userserver.modules.member.controller.auth.vo.MbrAuthLoginReqVO; 6 import cn.iocoder.yudao.userserver.modules.member.controller.auth.vo.MbrAuthLoginReqVO;
5 import cn.iocoder.yudao.userserver.modules.member.convert.user.MbrAuthConvert; 7 import cn.iocoder.yudao.userserver.modules.member.convert.user.MbrAuthConvert;
6 import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO; 8 import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO;
  9 +import cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants;
7 import cn.iocoder.yudao.userserver.modules.member.service.auth.MbrAuthService; 10 import cn.iocoder.yudao.userserver.modules.member.service.auth.MbrAuthService;
8 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService; 11 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
  12 +import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginLogTypeEnum;
  13 +import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginResultEnum;
  14 +import cn.iocoder.yudao.userserver.modules.system.service.auth.SysUserSessionService;
  15 +import cn.iocoder.yudao.userserver.modules.system.service.logger.SysLoginLogService;
  16 +import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  17 +import cn.iocoder.yudao.userserver.modules.system.service.logger.impl.SysLoginLogServiceImpl;
9 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
10 import org.springframework.context.annotation.Lazy; 19 import org.springframework.context.annotation.Lazy;
11 import org.springframework.security.authentication.AuthenticationManager; 20 import org.springframework.security.authentication.AuthenticationManager;
  21 +import org.springframework.security.authentication.BadCredentialsException;
  22 +import org.springframework.security.authentication.DisabledException;
  23 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  24 +import org.springframework.security.core.Authentication;
  25 +import org.springframework.security.core.AuthenticationException;
12 import org.springframework.security.core.userdetails.UserDetails; 26 import org.springframework.security.core.userdetails.UserDetails;
13 import org.springframework.security.core.userdetails.UsernameNotFoundException; 27 import org.springframework.security.core.userdetails.UsernameNotFoundException;
14 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
  29 +import org.springframework.util.Assert;
15 30
16 import javax.annotation.Resource; 31 import javax.annotation.Resource;
17 32
  33 +import java.util.Objects;
  34 +
  35 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  36 +import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.*;
  37 +
18 /** 38 /**
19 * Auth Service 实现类 39 * Auth Service 实现类
20 * 40 *
@@ -30,6 +50,10 @@ public class MbrAuthServiceImpl implements MbrAuthService { @@ -30,6 +50,10 @@ public class MbrAuthServiceImpl implements MbrAuthService {
30 50
31 @Resource 51 @Resource
32 private MbrUserService userService; 52 private MbrUserService userService;
  53 + @Resource
  54 + private SysLoginLogService loginLogService;
  55 + @Resource
  56 + private SysUserSessionService userSessionService;
33 57
34 @Override 58 @Override
35 public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException { 59 public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
@@ -44,7 +68,57 @@ public class MbrAuthServiceImpl implements MbrAuthService { @@ -44,7 +68,57 @@ public class MbrAuthServiceImpl implements MbrAuthService {
44 68
45 @Override 69 @Override
46 public String login(MbrAuthLoginReqVO reqVO, String userIp, String userAgent) { 70 public String login(MbrAuthLoginReqVO reqVO, String userIp, String userAgent) {
47 - return null; 71 + // 使用手机 + 密码,进行登录。
  72 + LoginUser loginUser = this.login0(reqVO.getMobile(), reqVO.getPassword());
  73 +
  74 + // 缓存登录用户到 Redis 中,返回 sessionId 编号
  75 + return userSessionService.createUserSession(loginUser, userIp, userAgent);
  76 + }
  77 +
  78 + private LoginUser login0(String username, String password) {
  79 + final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
  80 + // 用户验证
  81 + Authentication authentication;
  82 + try {
  83 + // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证
  84 + // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
  85 + authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
  86 + } catch (BadCredentialsException badCredentialsException) {
  87 + this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS);
  88 + throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
  89 + } catch (DisabledException disabledException) {
  90 + this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.USER_DISABLED);
  91 + throw exception(AUTH_LOGIN_USER_DISABLED);
  92 + } catch (AuthenticationException authenticationException) {
  93 + log.error("[login0][username({}) 发生未知异常]", username, authenticationException);
  94 + this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.UNKNOWN_ERROR);
  95 + throw exception(AUTH_LOGIN_FAIL_UNKNOWN);
  96 + }
  97 + // 登录成功的日志
  98 + Assert.notNull(authentication.getPrincipal(), "Principal 不会为空");
  99 + this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.SUCCESS);
  100 + return (LoginUser) authentication.getPrincipal();
  101 + }
  102 +
  103 + private void createLoginLog(String mobile, SysLoginLogTypeEnum logTypeEnum, SysLoginResultEnum loginResult) {
  104 + // 获得用户
  105 + MbrUserDO user = userService.getUserByMobile(mobile);
  106 + // 插入登录日志
  107 + SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
  108 + reqDTO.setLogType(logTypeEnum.getType());
  109 + reqDTO.setTraceId(TracerUtils.getTraceId());
  110 + if (user != null) {
  111 + reqDTO.setUserId(user.getId());
  112 + }
  113 + reqDTO.setUsername(mobile);
  114 + reqDTO.setUserAgent(ServletUtils.getUserAgent());
  115 + reqDTO.setUserIp(ServletUtils.getClientIP());
  116 + reqDTO.setResult(loginResult.getResult());
  117 + loginLogService.createLoginLog(reqDTO);
  118 + // 更新最后登录时间
  119 + if (user != null && Objects.equals(SysLoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
  120 + userService.updateUserLogin(user.getId(), ServletUtils.getClientIP());
  121 + }
48 } 122 }
49 123
50 @Override 124 @Override
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java
@@ -17,4 +17,12 @@ public interface MbrUserService { @@ -17,4 +17,12 @@ public interface MbrUserService {
17 */ 17 */
18 MbrUserDO getUserByMobile(String mobile); 18 MbrUserDO getUserByMobile(String mobile);
19 19
  20 + /**
  21 + * 更新用户的最后登陆信息
  22 + *
  23 + * @param id 用户编号
  24 + * @param loginIp 登陆 IP
  25 + */
  26 + void updateUserLogin(Long id, String loginIp);
  27 +
20 } 28 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java
@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service; @@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
8 8
9 import javax.annotation.Resource; 9 import javax.annotation.Resource;
10 import javax.validation.Valid; 10 import javax.validation.Valid;
  11 +import java.util.Date;
11 12
12 /** 13 /**
13 * User Service 实现类 14 * User Service 实现类
@@ -27,4 +28,9 @@ public class MbrUserServiceImpl implements MbrUserService { @@ -27,4 +28,9 @@ public class MbrUserServiceImpl implements MbrUserService {
27 return userMapper.selectByMobile(mobile); 28 return userMapper.selectByMobile(mobile);
28 } 29 }
29 30
  31 + @Override
  32 + public void updateUserLogin(Long id, String loginIp) {
  33 + userMapper.updateById(new MbrUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date()));
  34 + }
  35 +
30 } 36 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/logger/SysLoginLogConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.convert.logger;
  2 +
  3 +import cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger.SysLoginLogDO;
  4 +import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  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(SysLoginLogCreateReqDTO bean);
  14 +
  15 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/package-info.java
  1 +/**
  2 + * 提供 POJO 类的实体转换
  3 + *
  4 + * 目前使用 MapStruct 框架
  5 + */
1 package cn.iocoder.yudao.userserver.modules.system.convert; 6 package cn.iocoder.yudao.userserver.modules.system.convert;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/logger/SysLoginLogMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dal.dataobject.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger.SysLoginLogDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysLoginLogMapper extends BaseMapperX<SysLoginLogDO> {
  9 +
  10 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/logger/SysLoginLogDO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginLogTypeEnum;
  6 +import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginResultEnum;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.Data;
  9 +import lombok.EqualsAndHashCode;
  10 +import lombok.ToString;
  11 +
  12 +/**
  13 + * 登录日志表
  14 + *
  15 + * 注意,包括登录和登出两种行为
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +@TableName("sys_login_log")
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +public class SysLoginLogDO extends BaseDO {
  24 +
  25 + /**
  26 + * 日志主键
  27 + */
  28 + private Long id;
  29 + /**
  30 + * 日志类型
  31 + *
  32 + * 枚举 {@link SysLoginLogTypeEnum}
  33 + */
  34 + private Integer logType;
  35 + /**
  36 + * 链路追踪编号
  37 + */
  38 + private String traceId;
  39 + /**
  40 + * 用户编号
  41 + */
  42 + private Long userId;
  43 + /**
  44 + * 用户类型
  45 + *
  46 + * 枚举 {@link UserTypeEnum}
  47 + */
  48 + private Integer userType;
  49 + /**
  50 + * 用户账号
  51 + *
  52 + * 冗余,因为账号可以变更
  53 + */
  54 + private String username;
  55 + /**
  56 + * 登录结果
  57 + *
  58 + * 枚举 {@link SysLoginResultEnum}
  59 + */
  60 + private Integer result;
  61 + /**
  62 + * 用户 IP
  63 + */
  64 + private String userIp;
  65 + /**
  66 + * 浏览器 UA
  67 + */
  68 + private String userAgent;
  69 +
  70 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/package-info.java deleted
1 -package cn.iocoder.yudao.userserver.modules.system.dal.mysql;  
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/logger/SysLoginLogTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.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_USERNAME(100), // 使用账号登录
  14 + LOGIN_SOCIAL(101), // 使用社交登录
  15 + LOGIN_MOCK(102), // 使用 Mock 登录
  16 + LOGIN_MOBILE(103), // 使用手机登陆
  17 + LOGIN_SMS(104), // 使用短信登陆
  18 +
  19 + LOGOUT_SELF(200), // 自己主动登出
  20 + LOGOUT_TIMEOUT(201), // 超时登出
  21 + LOGOUT_DELETE(202), // 强制退出
  22 + ;
  23 +
  24 + /**
  25 + * 日志类型
  26 + */
  27 + private final Integer type;
  28 +
  29 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/logger/SysLoginResultEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.enums.logger;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 登录结果的枚举类
  8 + */
  9 +@Getter
  10 +@AllArgsConstructor
  11 +public enum SysLoginResultEnum {
  12 +
  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), // 未知异常
  20 + ;
  21 +
  22 + /**
  23 + * 结果
  24 + */
  25 + private final Integer result;
  26 +
  27 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.enums;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysUserSessionService.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.service.auth;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  4 +
  5 +/**
  6 + * 在线用户 Session Service 接口
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +public interface SysUserSessionService {
  11 +
  12 + /**
  13 + * 创建在线用户 Session
  14 + *
  15 + * @param loginUser 登录用户
  16 + * @param userIp 用户 IP
  17 + * @param userAgent 用户 UA
  18 + * @return Session 编号
  19 + */
  20 + String createUserSession(LoginUser loginUser, String userIp, String userAgent);
  21 +
  22 + /**
  23 + * 刷新在线用户 Session 的更新时间
  24 + *
  25 + * @param sessionId Session 编号
  26 + * @param loginUser 登录用户
  27 + */
  28 + void refreshUserSession(String sessionId, LoginUser loginUser);
  29 +
  30 + /**
  31 + * 删除在线用户 Session
  32 + *
  33 + * @param sessionId Session 编号
  34 + */
  35 + void deleteUserSession(String sessionId);
  36 +
  37 + /**
  38 + * 获得 Session 编号对应的在线用户
  39 + *
  40 + * @param sessionId Session 编号
  41 + * @return 在线用户
  42 + */
  43 + LoginUser getLoginUser(String sessionId);
  44 +
  45 + /**
  46 + * 获取当前登录用户信息
  47 + * @param username 用户名称
  48 + * @return 在线用户
  49 + */
  50 + String getSessionId(String username);
  51 +
  52 + /**
  53 + * 获得 Session 超时时间,单位:毫秒
  54 + *
  55 + * @return 超时时间
  56 + */
  57 + Long getSessionTimeoutMillis();
  58 +
  59 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.service.auth.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  4 +import cn.iocoder.yudao.userserver.modules.system.service.auth.SysUserSessionService;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.stereotype.Service;
  7 +
  8 +/**
  9 + * 在线用户 Session Service 实现类
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Service
  14 +@Slf4j
  15 +public class SysUserSessionServiceImpl implements SysUserSessionService {
  16 +
  17 + @Override
  18 + public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {
  19 + return null;
  20 + }
  21 +
  22 + @Override
  23 + public void refreshUserSession(String sessionId, LoginUser loginUser) {
  24 +
  25 + }
  26 +
  27 + @Override
  28 + public void deleteUserSession(String sessionId) {
  29 +
  30 + }
  31 +
  32 + @Override
  33 + public LoginUser getLoginUser(String sessionId) {
  34 + return null;
  35 + }
  36 +
  37 + @Override
  38 + public String getSessionId(String username) {
  39 + return null;
  40 + }
  41 +
  42 + @Override
  43 + public Long getSessionTimeoutMillis() {
  44 + return null;
  45 + }
  46 +
  47 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/logger/SysLoginLogService.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.service.logger;
  2 +
  3 +import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  4 +
  5 +/**
  6 + * 登录日志 Service 接口
  7 + */
  8 +public interface SysLoginLogService {
  9 +
  10 + /**
  11 + * 创建登录日志
  12 + *
  13 + * @param reqDTO 日志信息
  14 + */
  15 + void createLoginLog(SysLoginLogCreateReqDTO reqDTO);
  16 +
  17 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/logger/dto/SysLoginLogCreateReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.service.logger.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotBlank;
  6 +import javax.validation.constraints.NotEmpty;
  7 +import javax.validation.constraints.NotNull;
  8 +import javax.validation.constraints.Size;
  9 +
  10 +/**
  11 + * 登录日志创建 Request DTO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Data
  16 +public class SysLoginLogCreateReqDTO {
  17 +
  18 + /**
  19 + * 日志类型
  20 + */
  21 + @NotNull(message = "日志类型不能为空")
  22 + private Integer logType;
  23 + /**
  24 + * 链路追踪编号
  25 + */
  26 + @NotEmpty(message = "链路追踪编号不能为空")
  27 + private String traceId;
  28 +
  29 + /**
  30 + * 用户编号
  31 + */
  32 + private Long userId;
  33 + /**
  34 + * 用户账号
  35 + */
  36 + @NotBlank(message = "用户账号不能为空")
  37 + @Size(max = 30, message = "用户账号长度不能超过30个字符")
  38 + private String username;
  39 +
  40 + /**
  41 + * 登录结果
  42 + */
  43 + @NotNull(message = "登录结果不能为空")
  44 + private Integer result;
  45 +
  46 + /**
  47 + * 用户 IP
  48 + */
  49 + @NotEmpty(message = "用户 IP 不能为空")
  50 + private String userIp;
  51 + /**
  52 + * 浏览器 UserAgent
  53 + */
  54 + @NotEmpty(message = "浏览器 UserAgent 不能为空")
  55 + private String userAgent;
  56 +
  57 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.service.logger.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.userserver.modules.system.convert.logger.SysLoginLogConvert;
  5 +import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.logger.SysLoginLogMapper;
  6 +import cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger.SysLoginLogDO;
  7 +import cn.iocoder.yudao.userserver.modules.system.service.logger.SysLoginLogService;
  8 +import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  9 +import org.springframework.stereotype.Service;
  10 +
  11 +import javax.annotation.Resource;
  12 +
  13 +/**
  14 + * 登录日志 Service 实现
  15 + */
  16 +@Service
  17 +public class SysLoginLogServiceImpl implements SysLoginLogService {
  18 +
  19 + @Resource
  20 + private SysLoginLogMapper loginLogMapper;
  21 +
  22 + @Override
  23 + public void createLoginLog(SysLoginLogCreateReqDTO reqDTO) {
  24 + SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqDTO);
  25 + loginLog.setUserType(UserTypeEnum.MEMBER.getValue());
  26 + // 插入
  27 + loginLogMapper.insert(loginLog);
  28 + }
  29 +
  30 +}