Commit 024d44cea1d06ecf12f694340223d5bdd3eafb07

Authored by YunaiV
1 parent 71b9104a

1. 增加前台用户的 token 刷新

2. 增加前台用户的 logout 退出
Showing 13 changed files with 166 additions and 29 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
... ... @@ -16,10 +16,7 @@ public interface SysErrorCodeConstants {
16 16 ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在");
17 17 ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确");
18 18 ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
19   -
20   - // ========== TOKEN 模块 1002001000 ==========
21   - ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期");
22   - ErrorCode TOKEN_PARSE_FAIL = new ErrorCode(1002001001, "Token 解析失败");
  19 + ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");
23 20  
24 21 // ========== 菜单模块 1002002000 ==========
25 22 ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1002002000, "已经存在该名字的菜单");
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
... ... @@ -255,15 +255,15 @@ public class SysAuthServiceImpl implements SysAuthService {
255 255 }
256 256 // 删除 session
257 257 userSessionCoreService.deleteUserSession(token);
258   - // 记录登出日子和
259   - this.createLogoutLog(loginUser.getUsername());
  258 + // 记录登出日志
  259 + this.createLogoutLog(loginUser.getId(), loginUser.getUsername());
260 260 }
261 261  
262   - private void createLogoutLog(String username) {
263   - // TODO 芋艿:这里未设置 userId
  262 + private void createLogoutLog(Long userId, String username) {
264 263 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
265 264 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
266 265 reqDTO.setTraceId(TracerUtils.getTraceId());
  266 + reqDTO.setUserId(userId);
267 267 reqDTO.setUserType(UserTypeEnum.ADMIN.getValue());
268 268 reqDTO.setUsername(username);
269 269 reqDTO.setUserAgent(ServletUtils.getUserAgent());
... ... @@ -294,7 +294,7 @@ public class SysAuthServiceImpl implements SysAuthService {
294 294 // 重新加载 SysUserDO 信息
295 295 SysUserDO user = userService.getUser(loginUser.getId());
296 296 if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) {
297   - throw exception(TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面
  297 + throw exception(AUTH_TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面
298 298 }
299 299  
300 300 // 刷新 LoginUser 缓存
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java
1 1 package cn.iocoder.yudao.userserver.modules.member.service.user;
2 2  
  3 +import cn.iocoder.yudao.framework.common.validation.Mobile;
3 4 import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO;
4 5  
5 6 /**
... ... @@ -18,6 +19,16 @@ public interface MbrUserService {
18 19 MbrUserDO getUserByMobile(String mobile);
19 20  
20 21 /**
  22 + * 基于手机号创建用户。
  23 + * 如果用户已经存在,则直接进行返回
  24 + *
  25 + * @param mobile 手机号
  26 + * @param registerIp 注册 IP
  27 + * @return 用户对象
  28 + */
  29 + MbrUserDO createUserIfAbsent(@Mobile String mobile, String registerIp);
  30 +
  31 + /**
21 32 * 更新用户的最后登陆信息
22 33 *
23 34 * @param id 用户编号
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java
1 1 package cn.iocoder.yudao.userserver.modules.member.service.user.impl;
2 2  
  3 +import cn.hutool.core.util.IdUtil;
  4 +import cn.hutool.core.util.RandomUtil;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 7 import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO;
4 8 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
5 9 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
6 10 import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.security.crypto.password.PasswordEncoder;
7 12 import org.springframework.stereotype.Service;
8 13  
9 14 import javax.annotation.Resource;
... ... @@ -23,12 +28,39 @@ public class MbrUserServiceImpl implements MbrUserService {
23 28 @Resource
24 29 private MbrUserMapper userMapper;
25 30  
  31 + @Resource
  32 + private PasswordEncoder passwordEncoder;
  33 +
26 34 @Override
27 35 public MbrUserDO getUserByMobile(String mobile) {
28 36 return userMapper.selectByMobile(mobile);
29 37 }
30 38  
31 39 @Override
  40 + public MbrUserDO createUserIfAbsent(String mobile, String registerIp) {
  41 + // 用户已经存在
  42 + MbrUserDO user = userMapper.selectByMobile(mobile);
  43 + if (user != null) {
  44 + return user;
  45 + }
  46 + // 用户不存在,则进行创建
  47 + return this.createUser(mobile, registerIp);
  48 + }
  49 +
  50 + private MbrUserDO createUser(String mobile, String registerIp) {
  51 + // 生成密码
  52 + String password = IdUtil.fastSimpleUUID();
  53 + // 插入用户
  54 + MbrUserDO user = new MbrUserDO();
  55 + user.setMobile(mobile);
  56 + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
  57 + user.setPassword(passwordEncoder.encode(password)); // 加密密码
  58 + user.setRegisterIp(registerIp);
  59 + userMapper.insert(user);
  60 + return user;
  61 + }
  62 +
  63 + @Override
32 64 public void updateUserLogin(Long id, String loginIp) {
33 65 userMapper.updateById(new MbrUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date()));
34 66 }
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http
... ... @@ -12,6 +12,20 @@ POST {{userServerUrl}}/send-sms-code
12 12 Content-Type: application/json
13 13  
14 14 {
15   - "mobile": "15601691300",
  15 + "mobile": "15601691301",
16 16 "scene": 1
17 17 }
  18 +
  19 +### 请求 /sms-login 接口 => 成功
  20 +POST {{userServerUrl}}/sms-login
  21 +Content-Type: application/json
  22 +
  23 +{
  24 + "mobile": "15601691301",
  25 + "code": 9999
  26 +}
  27 +
  28 +### 请求 /logout 接口 => 成功
  29 +POST {{userServerUrl}}/logout
  30 +Content-Type: application/json
  31 +Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java
... ... @@ -33,28 +33,30 @@ public class SysAuthController {
33 33  
34 34 @PostMapping("/login")
35 35 @ApiOperation("使用手机 + 密码登录")
36   - public CommonResult<MbrAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
  36 + public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
37 37 String token = authService.login(reqVO, getClientIP(), getUserAgent());
38 38 // 返回结果
39   - return success(MbrAuthLoginRespVO.builder().token(token).build());
  39 + return success(SysAuthLoginRespVO.builder().token(token).build());
40 40 }
41 41  
42 42 @PostMapping("/sms-login")
43 43 @ApiOperation("使用手机 + 验证码登录")
44   - public CommonResult<MbrAuthLoginRespVO> smsLogin(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
45   - return null;
  44 + public CommonResult<SysAuthLoginRespVO> smsLogin(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) {
  45 + String token = authService.smsLogin(reqVO, getClientIP(), getUserAgent());
  46 + // 返回结果
  47 + return success(SysAuthLoginRespVO.builder().token(token).build());
46 48 }
47 49  
48 50 @PostMapping("/send-sms-code")
49 51 @ApiOperation("发送手机验证码")
50   - public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid MbrAuthSendSmsReqVO reqVO) {
  52 + public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) {
51 53 smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP());
52 54 return success(true);
53 55 }
54 56  
55 57 @PostMapping("/reset-password")
56 58 @ApiOperation(value = "重置密码", notes = "用户忘记密码时使用")
57   - public CommonResult<Boolean> resetPassword(@RequestBody @Valid SysAuthResetPasswordReqVO reqVO) {
  59 + public CommonResult<Boolean> resetPassword(@RequestBody @Valid MbrAuthResetPasswordReqVO reqVO) {
58 60 return null;
59 61 }
60 62  
... ... @@ -74,7 +76,7 @@ public class SysAuthController {
74 76  
75 77 @PostMapping("/social-login")
76 78 @ApiOperation("社交登录,使用 code 授权码")
77   - public CommonResult<MbrAuthLoginRespVO> socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) {
  79 + public CommonResult<SysAuthLoginRespVO> socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) {
78 80 // String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());
79 81 // // 返回结果
80 82 // return success(MbrAuthLoginRespVO.builder().token(token).build());
... ... @@ -83,7 +85,7 @@ public class SysAuthController {
83 85  
84 86 @PostMapping("/social-login2")
85 87 @ApiOperation("社交登录,使用 code 授权码 + 账号密码")
86   - public CommonResult<MbrAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) {
  88 + public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) {
87 89 // String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());
88 90 // // 返回结果
89 91 // return success(MbrAuthLoginRespVO.builder().token(token).build());
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthResetPasswordReqVO.java renamed to yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java
... ... @@ -16,7 +16,7 @@ import javax.validation.constraints.Pattern;
16 16 @NoArgsConstructor
17 17 @AllArgsConstructor
18 18 @Builder
19   -public class SysAuthResetPasswordReqVO {
  19 +public class MbrAuthResetPasswordReqVO {
20 20  
21 21 @ApiModelProperty(value = "新密码", required = true, example = "buzhidao")
22 22 @NotEmpty(message = "新密码不能为空")
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthLoginRespVO.java renamed to yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java
... ... @@ -12,7 +12,7 @@ import lombok.NoArgsConstructor;
12 12 @NoArgsConstructor
13 13 @AllArgsConstructor
14 14 @Builder
15   -public class MbrAuthLoginRespVO {
  15 +public class SysAuthLoginRespVO {
16 16  
17 17 @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
18 18 private String token;
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSendSmsReqVO.java renamed to yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java
... ... @@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
13 13 @ApiModel("发送手机验证码 Response VO")
14 14 @Data
15 15 @Accessors(chain = true)
16   -public class MbrAuthSendSmsReqVO {
  16 +public class SysAuthSendSmsReqVO {
17 17  
18 18 @ApiModelProperty(value = "手机号", example = "15601691234")
19 19 @Mobile
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSmsLoginReqVO.java renamed to yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java
... ... @@ -17,18 +17,13 @@ import javax.validation.constraints.Pattern;
17 17 @NoArgsConstructor
18 18 @AllArgsConstructor
19 19 @Builder
20   -public class MbrAuthSmsLoginReqVO {
  20 +public class SysAuthSmsLoginReqVO {
21 21  
22 22 @ApiModelProperty(value = "手机号", required = true, example = "15601691300")
23 23 @NotEmpty(message = "手机号不能为空")
24 24 @Mobile
25 25 private String mobile;
26 26  
27   - @ApiModelProperty(value = "密码", required = true, example = "buzhidao")
28   - @NotEmpty(message = "密码不能为空")
29   - @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
30   - private String password;
31   -
32 27 @ApiModelProperty(value = "手机验证码", required = true, example = "1024")
33 28 @NotEmpty(message = "手机验证码不能为空")
34 29 @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java
... ... @@ -13,6 +13,7 @@ public interface SysErrorCodeConstants {
13 13 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1005000000, "登录失败,账号密码不正确");
14 14 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1005000001, "登录失败,账号被禁用");
15 15 ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1005000002, "登录失败"); // 登录失败的兜底,未知原因
  16 + ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1005000003, "Token 已经过期");
16 17  
17 18 // ========== SMS CODE 模块 1005001000 ==========
18 19 ErrorCode USER_SMS_CODE_NOT_FOUND = new ErrorCode(1005001000, "验证码不存在");
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.userserver.modules.system.service.auth;
2 2  
3 3 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
4 4 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthLoginReqVO;
  5 +import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO;
5 6  
6 7 import javax.validation.Valid;
7 8  
... ... @@ -24,4 +25,14 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
24 25 */
25 26 String login(@Valid SysAuthLoginReqVO reqVO, String userIp, String userAgent);
26 27  
  28 + /**
  29 + * 手机 + 验证码登陆
  30 + *
  31 + * @param reqVO 登陆信息
  32 + * @param userIp 用户 IP
  33 + * @param userAgent 用户 UA
  34 + * @return 身份令牌,使用 JWT 方式
  35 + */
  36 + String smsLogin(@Valid SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent);
  37 +
27 38 }
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
1 1 package cn.iocoder.yudao.userserver.modules.system.service.auth.impl;
2 2  
  3 +import cn.hutool.core.lang.Assert;
3 4 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
4 5 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
5 6 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  7 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  8 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 9 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
7 10 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
8 11 import cn.iocoder.yudao.framework.security.core.LoginUser;
9 12 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthLoginReqVO;
  13 +import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO;
10 14 import cn.iocoder.yudao.userserver.modules.system.convert.auth.SysAuthConvert;
11 15 import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO;
  16 +import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
12 17 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
13 18 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
14 19 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum;
15 20 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum;
  21 +import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
16 22 import lombok.extern.slf4j.Slf4j;
17 23 import org.springframework.context.annotation.Lazy;
18 24 import org.springframework.security.authentication.AuthenticationManager;
... ... @@ -24,7 +30,7 @@ import org.springframework.security.core.AuthenticationException;
24 30 import org.springframework.security.core.userdetails.UserDetails;
25 31 import org.springframework.security.core.userdetails.UsernameNotFoundException;
26 32 import org.springframework.stereotype.Service;
27   -import org.springframework.util.Assert;
  33 +import org.springframework.transaction.annotation.Transactional;
28 34  
29 35 import javax.annotation.Resource;
30 36 import java.util.Objects;
... ... @@ -48,6 +54,8 @@ public class SysAuthServiceImpl implements SysAuthService {
48 54 @Resource
49 55 private MbrUserService userService;
50 56 @Resource
  57 + private SysSmsCodeService smsCodeService;
  58 + @Resource
51 59 private SysLoginLogCoreService loginLogCoreService;
52 60 @Resource
53 61 private SysUserSessionCoreService userSessionCoreService;
... ... @@ -72,6 +80,25 @@ public class SysAuthServiceImpl implements SysAuthService {
72 80 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
73 81 }
74 82  
  83 + @Override
  84 + @Transactional
  85 + public String smsLogin(SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent) {
  86 + // 校验验证码
  87 + smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.LOGIN_BY_SMS.getScene(),
  88 + reqVO.getCode(), userIp);
  89 +
  90 + // 获得获得注册用户
  91 + MbrUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp);
  92 + Assert.notNull(user, "获取用户失败,结果为空");
  93 +
  94 + // 执行登陆
  95 + this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SMS, SysLoginResultEnum.SUCCESS);
  96 + LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
  97 +
  98 + // 缓存登录用户到 Redis 中,返回 sessionId 编号
  99 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
  100 + }
  101 +
75 102 private LoginUser login0(String username, String password) {
76 103 final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
77 104 // 用户验证
... ... @@ -120,7 +147,31 @@ public class SysAuthServiceImpl implements SysAuthService {
120 147  
121 148 @Override
122 149 public LoginUser verifyTokenAndRefresh(String token) {
123   - return null;
  150 + // 获得 LoginUser
  151 + LoginUser loginUser = userSessionCoreService.getLoginUser(token);
  152 + if (loginUser == null) {
  153 + return null;
  154 + }
  155 + // 刷新 LoginUser 缓存
  156 + this.refreshLoginUserCache(token, loginUser);
  157 + return loginUser;
  158 + }
  159 +
  160 + private void refreshLoginUserCache(String token, LoginUser loginUser) {
  161 + // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
  162 + if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
  163 + userSessionCoreService.getSessionTimeoutMillis() / 3) {
  164 + return;
  165 + }
  166 +
  167 + // 重新加载 MbrUserDO 信息
  168 + MbrUserDO user = userService.getUser(loginUser.getId());
  169 + if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) {
  170 + throw exception(AUTH_TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面
  171 + }
  172 +
  173 + // 刷新 LoginUser 缓存
  174 + userSessionCoreService.refreshUserSession(token, loginUser);
124 175 }
125 176  
126 177 @Override
... ... @@ -130,6 +181,8 @@ public class SysAuthServiceImpl implements SysAuthService {
130 181 if (user == null) {
131 182 throw new UsernameNotFoundException(String.valueOf(userId));
132 183 }
  184 +
  185 + // 执行登陆
133 186 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
134 187  
135 188 // 创建 LoginUser 对象
... ... @@ -138,7 +191,28 @@ public class SysAuthServiceImpl implements SysAuthService {
138 191  
139 192 @Override
140 193 public void logout(String token) {
  194 + // 查询用户信息
  195 + LoginUser loginUser = userSessionCoreService.getLoginUser(token);
  196 + if (loginUser == null) {
  197 + return;
  198 + }
  199 + // 删除 session
  200 + userSessionCoreService.deleteUserSession(token);
  201 + // 记录登出日志
  202 + this.createLogoutLog(loginUser.getId(), loginUser.getUsername());
  203 + }
141 204  
  205 + private void createLogoutLog(Long userId, String username) {
  206 + SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
  207 + reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
  208 + reqDTO.setTraceId(TracerUtils.getTraceId());
  209 + reqDTO.setUserId(userId);
  210 + reqDTO.setUserType(UserTypeEnum.MEMBER.getValue());
  211 + reqDTO.setUsername(username);
  212 + reqDTO.setUserAgent(ServletUtils.getUserAgent());
  213 + reqDTO.setUserIp(ServletUtils.getClientIP());
  214 + reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult());
  215 + loginLogCoreService.createLoginLog(reqDTO);
142 216 }
143 217  
144 218 }
... ...