Commit 5ea9cc3cd796db0eede69e792d842b7754ffde34

Authored by YunaiV
1 parent 4f52d136

实现管理后台登出时,删除 oauth 令牌

Showing 13 changed files with 90 additions and 395 deletions
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.security.core.filter; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.security.core.filter;
2 2
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.exception.ServiceException;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 7 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
7 import cn.iocoder.yudao.framework.security.config.SecurityProperties; 8 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
@@ -44,23 +45,14 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { @@ -44,23 +45,14 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
44 if (StrUtil.isNotEmpty(token)) { 45 if (StrUtil.isNotEmpty(token)) {
45 Integer userType = WebFrameworkUtils.getLoginUserType(request); 46 Integer userType = WebFrameworkUtils.getLoginUserType(request);
46 try { 47 try {
47 - // 验证 token 有效性  
48 - OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token);  
49 - if (accessToken != null && ObjectUtil.notEqual(accessToken.getUserType(), userType)) { // 用户类型不匹配,无权限  
50 - throw new AccessDeniedException("错误的用户类型");  
51 - }  
52 - LoginUser loginUser = null;  
53 - if (accessToken != null) { // 如果不为空,说明认证通过,则转换成登录用户  
54 - loginUser = new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())  
55 - .setTenantId(accessToken.getTenantId());  
56 - }  
57 -  
58 - // 模拟 Login 功能,方便日常开发调试 48 + // 1.1 基于 token 构建登录用户
  49 + LoginUser loginUser = buildLoginUserByToken(token, userType);
  50 + // 1.2 模拟 Login 功能,方便日常开发调试
59 if (loginUser == null) { 51 if (loginUser == null) {
60 loginUser = mockLoginUser(request, token, userType); 52 loginUser = mockLoginUser(request, token, userType);
61 } 53 }
62 54
63 - // 设置当前用户 55 + // 2. 设置当前用户
64 if (loginUser != null) { 56 if (loginUser != null) {
65 SecurityFrameworkUtils.setLoginUser(loginUser, request); 57 SecurityFrameworkUtils.setLoginUser(loginUser, request);
66 } 58 }
@@ -75,6 +67,25 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { @@ -75,6 +67,25 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
75 chain.doFilter(request, response); 67 chain.doFilter(request, response);
76 } 68 }
77 69
  70 + private LoginUser buildLoginUserByToken(String token, Integer userType) {
  71 + try {
  72 + OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token);
  73 + if (accessToken == null) {
  74 + return null;
  75 + }
  76 + // 用户类型不匹配,无权限
  77 + if (ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
  78 + throw new AccessDeniedException("错误的用户类型");
  79 + }
  80 + // 构建登录用户
  81 + return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
  82 + .setTenantId(accessToken.getTenantId());
  83 + } catch (ServiceException serviceException) {
  84 + // 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可
  85 + return null;
  86 + }
  87 + }
  88 +
78 /** 89 /**
79 * 模拟登录用户,方便日常开发调试 90 * 模拟登录用户,方便日常开发调试
80 * 91 *
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java
@@ -16,7 +16,6 @@ public enum LoginLogTypeEnum { @@ -16,7 +16,6 @@ public enum LoginLogTypeEnum {
16 LOGIN_SMS(104), // 使用短信登陆 16 LOGIN_SMS(104), // 使用短信登陆
17 17
18 LOGOUT_SELF(200), // 自己主动登出 18 LOGOUT_SELF(200), // 自己主动登出
19 - LOGOUT_TIMEOUT(201), // 超时登出  
20 LOGOUT_DELETE(202), // 强制退出 19 LOGOUT_DELETE(202), // 强制退出
21 ; 20 ;
22 21
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -33,8 +33,6 @@ import java.util.List; @@ -33,8 +33,6 @@ import java.util.List;
33 import java.util.Set; 33 import java.util.Set;
34 34
35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
36 -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;  
37 -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;  
38 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 36 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
39 import static java.util.Collections.singleton; 37 import static java.util.Collections.singleton;
40 38
@@ -63,7 +61,7 @@ public class AuthController { @@ -63,7 +61,7 @@ public class AuthController {
63 @ApiOperation("使用账号密码登录") 61 @ApiOperation("使用账号密码登录")
64 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 62 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
65 public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) { 63 public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
66 - String token = authService.login(reqVO, getClientIP(), getUserAgent()); 64 + String token = authService.login(reqVO);
67 return success(AuthLoginRespVO.builder().token(token).build()); 65 return success(AuthLoginRespVO.builder().token(token).build());
68 } 66 }
69 67
@@ -116,7 +114,7 @@ public class AuthController { @@ -116,7 +114,7 @@ public class AuthController {
116 @ApiOperation("使用短信验证码登录") 114 @ApiOperation("使用短信验证码登录")
117 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 115 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
118 public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) { 116 public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
119 - String token = authService.smsLogin(reqVO, getClientIP(), getUserAgent()); 117 + String token = authService.smsLogin(reqVO);
120 // 返回结果 118 // 返回结果
121 return success(AuthLoginRespVO.builder().token(token).build()); 119 return success(AuthLoginRespVO.builder().token(token).build());
122 } 120 }
@@ -146,7 +144,7 @@ public class AuthController { @@ -146,7 +144,7 @@ public class AuthController {
146 @ApiOperation("社交快捷登录,使用 code 授权码") 144 @ApiOperation("社交快捷登录,使用 code 授权码")
147 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 145 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
148 public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) { 146 public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) {
149 - String token = authService.socialQuickLogin(reqVO, getClientIP(), getUserAgent()); 147 + String token = authService.socialQuickLogin(reqVO);
150 return success(AuthLoginRespVO.builder().token(token).build()); 148 return success(AuthLoginRespVO.builder().token(token).build());
151 } 149 }
152 150
@@ -154,7 +152,7 @@ public class AuthController { @@ -154,7 +152,7 @@ public class AuthController {
154 @ApiOperation("社交绑定登录,使用 code 授权码 + 账号密码") 152 @ApiOperation("社交绑定登录,使用 code 授权码 + 账号密码")
155 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 153 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
156 public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) { 154 public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) {
157 - String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent()); 155 + String token = authService.socialBindLogin(reqVO);
158 return success(AuthLoginRespVO.builder().token(token).build()); 156 return success(AuthLoginRespVO.builder().token(token).build());
159 } 157 }
160 158
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/auth/OAuth2RefreshTokenMapper.java
1 package cn.iocoder.yudao.module.system.dal.mysql.auth; 1 package cn.iocoder.yudao.module.system.dal.mysql.auth;
2 2
  3 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
3 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2RefreshTokenDO; 4 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2RefreshTokenDO;
4 -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;  
5 import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
7 7
8 @Mapper 8 @Mapper
9 public interface OAuth2RefreshTokenMapper extends BaseMapper<OAuth2RefreshTokenDO> { 9 public interface OAuth2RefreshTokenMapper extends BaseMapper<OAuth2RefreshTokenDO> {
10 10
11 - default int deleteByUserIdAndUserType(Integer userId, Integer userType) {  
12 - return delete(new QueryWrapper<OAuth2RefreshTokenDO>()  
13 - .eq("user_id", userId).eq("user_type", userType)); 11 + default int deleteByRefreshToken(String refreshToken) {
  12 + return delete(new LambdaQueryWrapperX<OAuth2RefreshTokenDO>()
  13 + .eq(OAuth2RefreshTokenDO::getRefreshToken, refreshToken));
14 } 14 }
15 15
16 } 16 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/auth/UserSessionTimeoutJob.java deleted
1 -package cn.iocoder.yudao.module.system.job.auth;  
2 -  
3 -import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;  
4 -import cn.iocoder.yudao.module.system.service.auth.UserSessionService;  
5 -import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;  
6 -import lombok.extern.slf4j.Slf4j;  
7 -import org.springframework.stereotype.Component;  
8 -  
9 -import javax.annotation.Resource;  
10 -  
11 -/**  
12 - * 用户 Session 超时 Job  
13 - *  
14 - * @author 願  
15 - */  
16 -@Component  
17 -@TenantJob  
18 -@Slf4j  
19 -public class UserSessionTimeoutJob implements JobHandler {  
20 -  
21 - @Resource  
22 - private UserSessionService userSessionService;  
23 -  
24 - @Override  
25 - public String execute(String param) throws Exception {  
26 - // 执行过期  
27 - Long timeoutCount = userSessionService.deleteTimeoutSession();  
28 - // 返回结果,记录每次的超时数量  
29 - return String.format("移除在线会话数量为 %s 个", timeoutCount);  
30 - }  
31 -  
32 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
@@ -17,11 +17,9 @@ public interface AdminAuthService { @@ -17,11 +17,9 @@ public interface AdminAuthService {
17 * 账号登录 17 * 账号登录
18 * 18 *
19 * @param reqVO 登录信息 19 * @param reqVO 登录信息
20 - * @param userIp 用户 IP  
21 - * @param userAgent 用户 UA  
22 * @return 身份令牌,使用 JWT 方式 20 * @return 身份令牌,使用 JWT 方式
23 */ 21 */
24 - String login(@Valid AuthLoginReqVO reqVO, String userIp, String userAgent); 22 + String login(@Valid AuthLoginReqVO reqVO);
25 23
26 /** 24 /**
27 * 基于 token 退出登录 25 * 基于 token 退出登录
@@ -41,21 +39,17 @@ public interface AdminAuthService { @@ -41,21 +39,17 @@ public interface AdminAuthService {
41 * 短信登录 39 * 短信登录
42 * 40 *
43 * @param reqVO 登录信息 41 * @param reqVO 登录信息
44 - * @param userIp 用户 IP  
45 - * @param userAgent 用户 UA  
46 * @return 身份令牌,使用 JWT 方式 42 * @return 身份令牌,使用 JWT 方式
47 */ 43 */
48 - String smsLogin(AuthSmsLoginReqVO reqVO, String userIp, String userAgent) ; 44 + String smsLogin(AuthSmsLoginReqVO reqVO) ;
49 45
50 /** 46 /**
51 * 社交快捷登录,使用 code 授权码 47 * 社交快捷登录,使用 code 授权码
52 * 48 *
53 * @param reqVO 登录信息 49 * @param reqVO 登录信息
54 - * @param userIp 用户 IP  
55 - * @param userAgent 用户 UA  
56 * @return 身份令牌,使用 JWT 方式 50 * @return 身份令牌,使用 JWT 方式
57 */ 51 */
58 - String socialQuickLogin(@Valid AuthSocialQuickLoginReqVO reqVO, String userIp, String userAgent); 52 + String socialQuickLogin(@Valid AuthSocialQuickLoginReqVO reqVO);
59 53
60 /** 54 /**
61 * 社交绑定登录,使用 code 授权码 + 账号密码 55 * 社交绑定登录,使用 code 授权码 + 账号密码
@@ -65,6 +59,6 @@ public interface AdminAuthService { @@ -65,6 +59,6 @@ public interface AdminAuthService {
65 * @param userAgent 用户 UA 59 * @param userAgent 用户 UA
66 * @return 身份令牌,使用 JWT 方式 60 * @return 身份令牌,使用 JWT 方式
67 */ 61 */
68 - String socialBindLogin(@Valid AuthSocialBindLoginReqVO reqVO, String userIp, String userAgent); 62 + String socialBindLogin(@Valid AuthSocialBindLoginReqVO reqVO);
69 63
70 } 64 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -6,11 +6,11 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -6,11 +6,11 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 6 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
7 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 7 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
8 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 8 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
9 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
10 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; 9 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
11 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 10 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
12 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; 11 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
13 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; 12 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
  13 +import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
14 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; 14 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
15 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; 15 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
16 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; 16 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
@@ -47,8 +47,6 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -47,8 +47,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
47 @Resource 47 @Resource
48 private LoginLogService loginLogService; 48 private LoginLogService loginLogService;
49 @Resource 49 @Resource
50 - private UserSessionService userSessionService;  
51 - @Resource  
52 private OAuth2TokenService oauth2TokenService; 50 private OAuth2TokenService oauth2TokenService;
53 @Resource 51 @Resource
54 private SocialUserService socialUserService; 52 private SocialUserService socialUserService;
@@ -60,16 +58,15 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -60,16 +58,15 @@ public class AdminAuthServiceImpl implements AdminAuthService {
60 private SmsCodeApi smsCodeApi; 58 private SmsCodeApi smsCodeApi;
61 59
62 @Override 60 @Override
63 - public String login(AuthLoginReqVO reqVO, String userIp, String userAgent) { 61 + public String login(AuthLoginReqVO reqVO) {
64 // 判断验证码是否正确 62 // 判断验证码是否正确
65 verifyCaptcha(reqVO); 63 verifyCaptcha(reqVO);
66 64
67 // 使用账号密码,进行登录 65 // 使用账号密码,进行登录
68 - LoginUser loginUser = login0(reqVO.getUsername(), reqVO.getPassword()); 66 + AdminUserDO user = login0(reqVO.getUsername(), reqVO.getPassword());
69 67
70 - // 缓存登陆用户到 Redis 中,返回 Token 令牌  
71 - return createUserSessionAfterLoginSuccess(loginUser, reqVO.getUsername(),  
72 - LoginLogTypeEnum.LOGIN_USERNAME, userIp, userAgent); 68 + // 创建 Token 令牌,记录登录日志
  69 + return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
73 } 70 }
74 71
75 @Override 72 @Override
@@ -83,9 +80,9 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -83,9 +80,9 @@ public class AdminAuthServiceImpl implements AdminAuthService {
83 } 80 }
84 81
85 @Override 82 @Override
86 - public String smsLogin(AuthSmsLoginReqVO reqVO, String userIp, String userAgent) { 83 + public String smsLogin(AuthSmsLoginReqVO reqVO) {
87 // 校验验证码 84 // 校验验证码
88 - smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), userIp)); 85 + smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), getClientIP()));
89 86
90 // 获得用户信息 87 // 获得用户信息
91 AdminUserDO user = userService.getUserByMobile(reqVO.getMobile()); 88 AdminUserDO user = userService.getUserByMobile(reqVO.getMobile());
@@ -93,12 +90,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -93,12 +90,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
93 throw exception(USER_NOT_EXISTS); 90 throw exception(USER_NOT_EXISTS);
94 } 91 }
95 92
96 - // 创建 LoginUser 对象  
97 - LoginUser loginUser = buildLoginUser(user);  
98 -  
99 // 缓存登陆用户到 Redis 中,返回 sessionId 编号 93 // 缓存登陆用户到 Redis 中,返回 sessionId 编号
100 - return createUserSessionAfterLoginSuccess(loginUser, reqVO.getMobile(),  
101 - LoginLogTypeEnum.LOGIN_MOBILE, userIp, userAgent); 94 + return createTokenAfterLoginSuccess(user.getId(), reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE);
102 } 95 }
103 96
104 @VisibleForTesting 97 @VisibleForTesting
@@ -128,7 +121,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -128,7 +121,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
128 } 121 }
129 122
130 @VisibleForTesting 123 @VisibleForTesting
131 - LoginUser login0(String username, String password) { 124 + AdminUserDO login0(String username, String password) {
132 final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; 125 final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
133 // 校验账号是否存在 126 // 校验账号是否存在
134 AdminUserDO user = userService.getUserByUsername(username); 127 AdminUserDO user = userService.getUserByUsername(username);
@@ -145,9 +138,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -145,9 +138,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
145 createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED); 138 createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
146 throw exception(AUTH_LOGIN_USER_DISABLED); 139 throw exception(AUTH_LOGIN_USER_DISABLED);
147 } 140 }
148 -  
149 - // 构建 User 对象  
150 - return buildLoginUser(user); 141 + return user;
151 } 142 }
152 143
153 private void createLoginLog(Long userId, String username, 144 private void createLoginLog(Long userId, String username,
@@ -170,7 +161,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -170,7 +161,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
170 } 161 }
171 162
172 @Override 163 @Override
173 - public String socialQuickLogin(AuthSocialQuickLoginReqVO reqVO, String userIp, String userAgent) { 164 + public String socialQuickLogin(AuthSocialQuickLoginReqVO reqVO) {
174 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 165 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
175 Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), 166 Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(),
176 reqVO.getCode(), reqVO.getState()); 167 reqVO.getCode(), reqVO.getState());
@@ -178,56 +169,46 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -178,56 +169,46 @@ public class AdminAuthServiceImpl implements AdminAuthService {
178 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 169 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
179 } 170 }
180 171
181 - // 自动登录 172 + // 获得用户
182 AdminUserDO user = userService.getUser(userId); 173 AdminUserDO user = userService.getUser(userId);
183 if (user == null) { 174 if (user == null) {
184 throw exception(USER_NOT_EXISTS); 175 throw exception(USER_NOT_EXISTS);
185 } 176 }
186 177
187 - // 创建 LoginUser 对象  
188 - LoginUser loginUser = buildLoginUser(user);  
189 -  
190 - // 缓存登录用户到 Redis 中,返回 Token 令牌  
191 - return createUserSessionAfterLoginSuccess(loginUser, null,  
192 - LoginLogTypeEnum.LOGIN_SOCIAL, userIp, userAgent); 178 + // 创建 Token 令牌,记录登录日志
  179 + return createTokenAfterLoginSuccess(user.getId(), null, LoginLogTypeEnum.LOGIN_SOCIAL);
193 } 180 }
194 181
195 @Override 182 @Override
196 - public String socialBindLogin(AuthSocialBindLoginReqVO reqVO, String userIp, String userAgent) { 183 + public String socialBindLogin(AuthSocialBindLoginReqVO reqVO) {
197 // 使用账号密码,进行登录。 184 // 使用账号密码,进行登录。
198 - LoginUser loginUser = login0(reqVO.getUsername(), reqVO.getPassword()); 185 + AdminUserDO user = login0(reqVO.getUsername(), reqVO.getPassword());
199 186
200 // 绑定社交用户 187 // 绑定社交用户
201 - socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); 188 + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(user.getId(), getUserType().getValue(), reqVO));
202 189
203 - // 缓存登录用户到 Redis 中,返回 Token 令牌  
204 - return createUserSessionAfterLoginSuccess(loginUser, reqVO.getUsername(),  
205 - LoginLogTypeEnum.LOGIN_SOCIAL, userIp, userAgent); 190 + // 创建 Token 令牌,记录登录日志
  191 + return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
206 } 192 }
207 193
208 - private String createUserSessionAfterLoginSuccess(LoginUser loginUser, String username,  
209 - LoginLogTypeEnum logType, String userIp, String userAgent) { 194 + private String createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
210 // 插入登陆日志 195 // 插入登陆日志
211 - createLoginLog(loginUser.getId(), username, logType, LoginResultEnum.SUCCESS); 196 + createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
212 // 创建访问令牌 197 // 创建访问令牌
213 - // TODO userIp、userAgent  
214 // TODO clientId 198 // TODO clientId
215 - return oauth2TokenService.createAccessToken(loginUser.getId(), getUserType().getValue(), 1L) 199 + return oauth2TokenService.createAccessToken(userId, getUserType().getValue(), 1L)
216 .getAccessToken(); 200 .getAccessToken();
217 -// return userSessionService.createUserSession(loginUser, userIp, userAgent);  
218 } 201 }
219 202
220 @Override 203 @Override
221 public void logout(String token) { 204 public void logout(String token) {
222 - // 查询用户信息  
223 - LoginUser loginUser = userSessionService.getLoginUser(token);  
224 - if (loginUser == null) { 205 + // 删除访问令牌
  206 + OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(token);
  207 + if (accessTokenDO == null) {
225 return; 208 return;
226 } 209 }
227 - // 删除 session  
228 - userSessionService.deleteUserSession(token);  
229 - // 记录登出日志  
230 - createLogoutLog(loginUser.getId()); 210 + // 删除成功,则记录登出日志
  211 + createLogoutLog(accessTokenDO.getUserId());
231 } 212 }
232 213
233 private void createLogoutLog(Long userId) { 214 private void createLogoutLog(Long userId) {
@@ -243,10 +224,6 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -243,10 +224,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
243 loginLogService.createLoginLog(reqDTO); 224 loginLogService.createLoginLog(reqDTO);
244 } 225 }
245 226
246 - private LoginUser buildLoginUser(AdminUserDO user) {  
247 - return AuthConvert.INSTANCE.convert(user).setUserType(getUserType().getValue());  
248 - }  
249 -  
250 private String getUsername(Long userId) { 227 private String getUsername(Long userId) {
251 if (userId == null) { 228 if (userId == null) {
252 return null; 229 return null;
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2TokenService.java
@@ -59,8 +59,8 @@ public interface OAuth2TokenService { @@ -59,8 +59,8 @@ public interface OAuth2TokenService {
59 * 参考 DefaultTokenServices 的 revokeToken 方法 59 * 参考 DefaultTokenServices 的 revokeToken 方法
60 * 60 *
61 * @param accessToken 刷新令牌 61 * @param accessToken 刷新令牌
62 - * @return 是否移除到 62 + * @return 访问令牌的信息
63 */ 63 */
64 - boolean removeAccessToken(String accessToken); 64 + OAuth2AccessTokenDO removeAccessToken(String accessToken);
65 65
66 } 66 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2TokenServiceImpl.java
@@ -85,23 +85,19 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { @@ -85,23 +85,19 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
85 } 85 }
86 86
87 @Override 87 @Override
88 - public boolean removeAccessToken(String accessToken) {  
89 - return false; 88 + public OAuth2AccessTokenDO removeAccessToken(String accessToken) {
  89 + // 删除访问令牌
  90 + OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(accessToken);
  91 + if (accessTokenDO == null) {
  92 + return null;
  93 + }
  94 + oauth2AccessTokenMapper.deleteById(accessTokenDO.getId());
  95 + oauth2AccessTokenRedisDAO.delete(accessToken);
  96 + // 删除刷新令牌
  97 + oauth2RefreshTokenMapper.deleteByRefreshToken(accessTokenDO.getRefreshToken());
  98 + return accessTokenDO;
90 } 99 }
91 100
92 -// @Override  
93 -// @Transactional  
94 -// public OAuth2AccessTokenRespDTO checkAccessToken(String accessToken) {  
95 -// OAuth2AccessTokenDO accessTokenDO = this.getOAuth2AccessToken(accessToken);  
96 -// if (accessTokenDO == null) { // 不存在  
97 -// throw ServiceExceptionUtil.exception(OAUTH2_ACCESS_TOKEN_NOT_FOUND);  
98 -// }  
99 -// if (accessTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期  
100 -// throw ServiceExceptionUtil.exception(OAUTH2_ACCESS_TOKEN_TOKEN_EXPIRED);  
101 -// }  
102 -// // 返回访问令牌  
103 -// return OAuth2Convert.INSTANCE.convert(accessTokenDO);  
104 -// }  
105 101
106 // @Override 102 // @Override
107 // @Transactional 103 // @Transactional
@@ -125,20 +121,6 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { @@ -125,20 +121,6 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
125 // // 返回访问令牌 121 // // 返回访问令牌
126 // return OAuth2Convert.INSTANCE.convert(oauth2AccessTokenDO); 122 // return OAuth2Convert.INSTANCE.convert(oauth2AccessTokenDO);
127 // } 123 // }
128 -//  
129 -// @Override  
130 -// @Transactional  
131 -// public void removeToken(OAuth2RemoveTokenByUserReqDTO removeTokenDTO) {  
132 -// // 删除 Access Token  
133 -// OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByUserIdAndUserType(  
134 -// removeTokenDTO.getUserId(), removeTokenDTO.getUserType());  
135 -// if (accessTokenDO != null) {  
136 -// this.deleteOAuth2AccessToken(accessTokenDO.getId());  
137 -// }  
138 -//  
139 -// // 删除 Refresh Token  
140 -// oauth2RefreshTokenMapper.deleteByUserIdAndUserType(removeTokenDTO.getUserId(), removeTokenDTO.getUserType());  
141 -// }  
142 124
143 private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2RefreshTokenDO refreshTokenDO, OAuth2ClientDO clientDO) { 125 private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2RefreshTokenDO refreshTokenDO, OAuth2ClientDO clientDO) {
144 OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO().setAccessToken(generateAccessToken()) 126 OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO().setAccessToken(generateAccessToken())
@@ -158,19 +140,6 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { @@ -158,19 +140,6 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
158 return refreshToken; 140 return refreshToken;
159 } 141 }
160 142
161 -  
162 -// /**  
163 -// * 删除 accessToken 的 MySQL 与 Redis 的数据  
164 -// *  
165 -// * @param accessToken 访问令牌  
166 -// */  
167 -// private void deleteOAuth2AccessToken(String accessToken) {  
168 -// // 删除 MySQL  
169 -// oauth2AccessTokenMapper.deleteById(accessToken);  
170 -// // 删除 Redis  
171 -// oauth2AccessTokenRedisDAO.delete(accessToken);  
172 -// }  
173 -//  
174 private static String generateAccessToken() { 143 private static String generateAccessToken() {
175 return IdUtil.fastSimpleUUID(); 144 return IdUtil.fastSimpleUUID();
176 } 145 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionService.java
1 package cn.iocoder.yudao.module.system.service.auth; 1 package cn.iocoder.yudao.module.system.service.auth;
2 2
3 -import cn.iocoder.yudao.framework.security.core.LoginUser; 3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; 4 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
5 import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; 5 import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
6 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
7 6
8 /** 7 /**
9 * 在线用户 Session Service 接口 8 * 在线用户 Session Service 接口
@@ -21,31 +20,6 @@ public interface UserSessionService { @@ -21,31 +20,6 @@ public interface UserSessionService {
21 PageResult<UserSessionDO> getUserSessionPage(UserSessionPageReqVO reqVO); 20 PageResult<UserSessionDO> getUserSessionPage(UserSessionPageReqVO reqVO);
22 21
23 /** 22 /**
24 - * 移除超时的在线用户  
25 - *  
26 - * @return {@link Long } 移出的超时用户数量  
27 - **/  
28 - long deleteTimeoutSession();  
29 -  
30 - /**  
31 - * 创建在线用户 Session  
32 - *  
33 - * @param loginUser 登录用户  
34 - * @param userIp 用户 IP  
35 - * @param userAgent 用户 UA  
36 - * @return Token 令牌  
37 - */  
38 - String createUserSession(LoginUser loginUser, String userIp, String userAgent);  
39 -  
40 - /**  
41 - * 刷新在线用户 Session 的更新时间  
42 - *  
43 - * @param token 令牌  
44 - * @param loginUser 登录用户  
45 - */  
46 - void refreshUserSession(String token, LoginUser loginUser);  
47 -  
48 - /**  
49 * 删除在线用户 Session 23 * 删除在线用户 Session
50 * 24 *
51 * @param token token 令牌 25 * @param token token 令牌
@@ -59,19 +33,4 @@ public interface UserSessionService { @@ -59,19 +33,4 @@ public interface UserSessionService {
59 */ 33 */
60 void deleteUserSession(Long id); 34 void deleteUserSession(Long id);
61 35
62 - /**  
63 - * 获得 Token 对应的在线用户  
64 - *  
65 - * @param token 令牌  
66 - * @return 在线用户  
67 - */  
68 - LoginUser getLoginUser(String token);  
69 -  
70 - /**  
71 - * 获得 Session 超时时间,单位:毫秒  
72 - *  
73 - * @return 超时时间  
74 - */  
75 - Long getSessionTimeoutMillis();  
76 -  
77 } 36 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImpl.java
1 package cn.iocoder.yudao.module.system.service.auth; 1 package cn.iocoder.yudao.module.system.service.auth;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.IdUtil;  
5 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 6 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
8 import cn.iocoder.yudao.framework.security.config.SecurityProperties; 7 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
9 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
10 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; 8 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
11 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; 9 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
12 import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; 10 import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
@@ -21,12 +19,9 @@ import lombok.extern.slf4j.Slf4j; @@ -21,12 +19,9 @@ import lombok.extern.slf4j.Slf4j;
21 import org.springframework.stereotype.Service; 19 import org.springframework.stereotype.Service;
22 20
23 import javax.annotation.Resource; 21 import javax.annotation.Resource;
24 -import java.time.Duration;  
25 import java.util.Collection; 22 import java.util.Collection;
26 -import java.util.List;  
27 23
28 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 24 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
29 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;  
30 25
31 /** 26 /**
32 * 在线用户 Session Service 实现类 27 * 在线用户 Session Service 实现类
@@ -64,29 +59,6 @@ public class UserSessionServiceImpl implements UserSessionService { @@ -64,29 +59,6 @@ public class UserSessionServiceImpl implements UserSessionService {
64 return userSessionMapper.selectPage(reqVO, userIds); 59 return userSessionMapper.selectPage(reqVO, userIds);
65 } 60 }
66 61
67 - @Override  
68 - public long deleteTimeoutSession() {  
69 - // 获取 db 里已经超时的用户列表  
70 - List<UserSessionDO> timeoutSessions = userSessionMapper.selectListBySessionTimoutLt();  
71 - if (CollUtil.isEmpty(timeoutSessions)) {  
72 - return 0L;  
73 - }  
74 -  
75 - // 由于过期的用户一般不多,所以顺序遍历,进行清理  
76 - int count = 0;  
77 - for (UserSessionDO session : timeoutSessions) {  
78 - // 基于 Redis 二次判断,同时也保证 Redis Key 的立即过期,避免延迟导致浪费内存空间  
79 - if (loginUserRedisDAO.exists(session.getToken())) {  
80 - continue;  
81 - }  
82 - userSessionMapper.deleteById(session.getId());  
83 - // 记录退出日志  
84 - createLogoutLog(session, LoginLogTypeEnum.LOGOUT_TIMEOUT);  
85 - count++;  
86 - }  
87 - return count;  
88 - }  
89 -  
90 private void createLogoutLog(UserSessionDO session, LoginLogTypeEnum type) { 62 private void createLogoutLog(UserSessionDO session, LoginLogTypeEnum type) {
91 LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); 63 LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
92 reqDTO.setLogType(type.getType()); 64 reqDTO.setLogType(type.getType());
@@ -101,28 +73,6 @@ public class UserSessionServiceImpl implements UserSessionService { @@ -101,28 +73,6 @@ public class UserSessionServiceImpl implements UserSessionService {
101 } 73 }
102 74
103 @Override 75 @Override
104 - public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {  
105 - // 生成 Session 编号  
106 - String token = generateToken();  
107 - // 写入 Redis 缓存  
108 - loginUserRedisDAO.set(token, loginUser);  
109 - // 写入 DB 中  
110 - UserSessionDO userSession = UserSessionDO.builder().token(token)  
111 - .userId(loginUser.getId()).userType(loginUser.getUserType())  
112 - .userIp(userIp).userAgent(userAgent).username("")  
113 - .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())))  
114 - .build();  
115 - userSessionMapper.insert(userSession);  
116 - // 返回 Token 令牌  
117 - return token;  
118 - }  
119 -  
120 - @Override  
121 - public void refreshUserSession(String token, LoginUser loginUser) {  
122 -  
123 - }  
124 -  
125 - @Override  
126 public void deleteUserSession(String token) { 76 public void deleteUserSession(String token) {
127 // 删除 Redis 缓存 77 // 删除 Redis 缓存
128 loginUserRedisDAO.delete(token); 78 loginUserRedisDAO.delete(token);
@@ -145,23 +95,4 @@ public class UserSessionServiceImpl implements UserSessionService { @@ -145,23 +95,4 @@ public class UserSessionServiceImpl implements UserSessionService {
145 createLogoutLog(session, LoginLogTypeEnum.LOGOUT_DELETE); 95 createLogoutLog(session, LoginLogTypeEnum.LOGOUT_DELETE);
146 } 96 }
147 97
148 - @Override  
149 - public LoginUser getLoginUser(String token) {  
150 - return loginUserRedisDAO.get(token);  
151 - }  
152 -  
153 - @Override  
154 - public Long getSessionTimeoutMillis() {  
155 - return securityProperties.getSessionTimeout().toMillis();  
156 - }  
157 -  
158 - /**  
159 - * 生成 Token 令牌,目前采用 UUID 算法  
160 - *  
161 - * @return Session 编号  
162 - */  
163 - private static String generateToken() {  
164 - return IdUtil.fastSimpleUUID();  
165 - }  
166 -  
167 } 98 }
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java
@@ -70,7 +70,7 @@ public class AuthServiceImplTest extends BaseDbUnitTest { @@ -70,7 +70,7 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
70 when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true); 70 when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true);
71 71
72 // 调用 72 // 调用
73 - LoginUser loginUser = authService.login0(username, password); 73 + AdminUserDO loginUser = authService.login0(username, password);
74 // 校验 74 // 校验
75 assertPojoEquals(user, loginUser); 75 assertPojoEquals(user, loginUser);
76 } 76 }
@@ -182,8 +182,6 @@ public class AuthServiceImplTest extends BaseDbUnitTest { @@ -182,8 +182,6 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
182 @Test 182 @Test
183 public void testLogin_success() { 183 public void testLogin_success() {
184 // 准备参数 184 // 准备参数
185 - String userIp = randomString();  
186 - String userAgent = randomString();  
187 AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o -> 185 AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o ->
188 o.setUsername("test_username").setPassword("test_password")); 186 o.setUsername("test_username").setPassword("test_password"));
189 187
@@ -197,13 +195,14 @@ public class AuthServiceImplTest extends BaseDbUnitTest { @@ -197,13 +195,14 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
197 when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true); 195 when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
198 // mock 缓存登录用户到 Redis 196 // mock 缓存登录用户到 Redis
199 String token = randomString(); 197 String token = randomString();
200 - when(userSessionService.createUserSession(argThat(argument -> {  
201 - AssertUtils.assertPojoEquals(user, argument);  
202 - return true;  
203 - }), eq(userIp), eq(userAgent))).thenReturn(token); 198 +// when(userSessionService.createUserSession(argThat(argument -> {
  199 +// AssertUtils.assertPojoEquals(user, argument);
  200 +// return true;
  201 +// }), eq(userIp), eq(userAgent))).thenReturn(token);
  202 + // TODO 芋艿:oauth2
204 203
205 // 调用, 并断言异常 204 // 调用, 并断言异常
206 - String result = authService.login(reqVO, userIp, userAgent); 205 + String result = authService.login(reqVO);
207 assertEquals(token, result); 206 assertEquals(token, result);
208 // 校验调用参数 207 // 校验调用参数
209 verify(loginLogService).createLoginLog( 208 verify(loginLogService).createLoginLog(
@@ -219,7 +218,8 @@ public class AuthServiceImplTest extends BaseDbUnitTest { @@ -219,7 +218,8 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
219 String token = randomString(); 218 String token = randomString();
220 LoginUser loginUser = randomPojo(LoginUser.class); 219 LoginUser loginUser = randomPojo(LoginUser.class);
221 // mock 220 // mock
222 - when(userSessionService.getLoginUser(token)).thenReturn(loginUser); 221 +// when(userSessionService.getLoginUser(token)).thenReturn(loginUser);
  222 + // TODO @芋艿:oauth2
223 // 调用 223 // 调用
224 authService.logout(token); 224 authService.logout(token);
225 // 校验调用参数 225 // 校验调用参数
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImplTest.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.auth; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.auth;
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 -import cn.iocoder.yudao.framework.common.util.date.DateUtils;  
7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 6 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
8 import cn.iocoder.yudao.framework.security.config.SecurityProperties; 7 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
9 import cn.iocoder.yudao.framework.security.core.LoginUser; 8 import cn.iocoder.yudao.framework.security.core.LoginUser;
@@ -14,8 +13,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -14,8 +13,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
14 import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper; 13 import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper;
15 import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO; 14 import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO;
16 import cn.iocoder.yudao.module.system.enums.common.SexEnum; 15 import cn.iocoder.yudao.module.system.enums.common.SexEnum;
17 -import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;  
18 -import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;  
19 import cn.iocoder.yudao.module.system.service.logger.LoginLogService; 16 import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
20 import cn.iocoder.yudao.module.system.service.user.AdminUserService; 17 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
21 import org.junit.jupiter.api.BeforeEach; 18 import org.junit.jupiter.api.BeforeEach;
@@ -25,17 +22,15 @@ import org.springframework.context.annotation.Import; @@ -25,17 +22,15 @@ import org.springframework.context.annotation.Import;
25 22
26 import javax.annotation.Resource; 23 import javax.annotation.Resource;
27 import java.time.Duration; 24 import java.time.Duration;
28 -import java.util.Calendar;  
29 25
30 import static cn.hutool.core.util.RandomUtil.randomEle; 26 import static cn.hutool.core.util.RandomUtil.randomEle;
31 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;  
32 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
33 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; 28 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  29 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
34 import static java.util.Collections.singletonList; 30 import static java.util.Collections.singletonList;
35 -import static org.junit.jupiter.api.Assertions.*;  
36 -import static org.mockito.ArgumentMatchers.argThat; 31 +import static org.junit.jupiter.api.Assertions.assertEquals;
  32 +import static org.junit.jupiter.api.Assertions.assertNull;
37 import static org.mockito.ArgumentMatchers.eq; 33 import static org.mockito.ArgumentMatchers.eq;
38 -import static org.mockito.Mockito.verify;  
39 import static org.mockito.Mockito.when; 34 import static org.mockito.Mockito.when;
40 35
41 /** 36 /**
@@ -101,112 +96,6 @@ public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest { @@ -101,112 +96,6 @@ public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
101 } 96 }
102 97
103 @Test 98 @Test
104 - public void testClearSessionTimeout_none() {  
105 - // mock db 数据  
106 - UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {  
107 - o.setUserType(randomEle(UserTypeEnum.values()).getValue());  
108 - o.setSessionTimeout(addTime(Duration.ofDays(1)));  
109 - });  
110 - userSessionMapper.insert(userSession);  
111 -  
112 - // 调用  
113 - long count = userSessionService.deleteTimeoutSession();  
114 - // 断言  
115 - assertEquals(0, count);  
116 - assertPojoEquals(userSession, userSessionMapper.selectById(userSession.getId())); // 未删除  
117 - }  
118 -  
119 - @Test // Redis 还存在的情况  
120 - public void testClearSessionTimeout_exists() {  
121 - // mock db 数据  
122 - UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {  
123 - o.setUserType(randomEle(UserTypeEnum.values()).getValue());  
124 - o.setSessionTimeout(DateUtils.addDate(Calendar.DAY_OF_YEAR, -1));  
125 - });  
126 - userSessionMapper.insert(userSession);  
127 - // mock redis 数据  
128 - loginUserRedisDAO.set(userSession.getToken(), new LoginUser());  
129 -  
130 - // 调用  
131 - long count = userSessionService.deleteTimeoutSession();  
132 - // 断言  
133 - assertEquals(0, count);  
134 - assertPojoEquals(userSession, userSessionMapper.selectById(userSession.getId())); // 未删除  
135 - }  
136 -  
137 - @Test  
138 - public void testClearSessionTimeout_success() {  
139 - // mock db 数据  
140 - UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {  
141 - o.setUserType(randomEle(UserTypeEnum.values()).getValue());  
142 - o.setSessionTimeout(DateUtils.addDate(Calendar.DAY_OF_YEAR, -1));  
143 - });  
144 - userSessionMapper.insert(userSession);  
145 -  
146 - // 清空超时数据  
147 - long count = userSessionService.deleteTimeoutSession();  
148 - // 校验  
149 - assertEquals(1, count);  
150 - assertNull(userSessionMapper.selectById(userSession.getId())); // 已删除  
151 - verify(loginLogService).createLoginLog(argThat(loginLog -> {  
152 - assertPojoEquals(userSession, loginLog);  
153 - assertEquals(LoginLogTypeEnum.LOGOUT_TIMEOUT.getType(), loginLog.getLogType());  
154 - assertEquals(LoginResultEnum.SUCCESS.getResult(), loginLog.getResult());  
155 - return true;  
156 - }));  
157 - }  
158 -  
159 - @Test  
160 - public void testCreateUserSession_success() {  
161 - // 准备参数  
162 - String userIp = randomString();  
163 - String userAgent = randomString();  
164 - LoginUser loginUser = randomPojo(LoginUser.class, o -> {  
165 - o.setUserType(randomEle(UserTypeEnum.values()).getValue());  
166 - o.setTenantId(0L); // 租户设置为 0,因为暂未启用多租户组件  
167 - });  
168 -  
169 - // 调用  
170 - String token = userSessionService.createUserSession(loginUser, userIp, userAgent);  
171 - // 校验 UserSessionDO 记录  
172 - UserSessionDO userSessionDO = userSessionMapper.selectOne(UserSessionDO::getToken, token);  
173 - assertPojoEquals(loginUser, userSessionDO, "id", "updateTime");  
174 - assertEquals(token, userSessionDO.getToken());  
175 - assertEquals(userIp, userSessionDO.getUserIp());  
176 - assertEquals(userAgent, userSessionDO.getUserAgent());  
177 - // 校验 LoginUser 缓存  
178 - LoginUser redisLoginUser = loginUserRedisDAO.get(token);  
179 - assertPojoEquals(loginUser, redisLoginUser, "username", "password");  
180 - }  
181 -  
182 - @Test  
183 - public void testCreateRefreshUserSession() {  
184 - // 准备参数  
185 - String token = randomString();  
186 -  
187 - // mock redis 数据  
188 - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue()));  
189 - loginUserRedisDAO.set(token, loginUser);  
190 - // mock db 数据  
191 - UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {  
192 - o.setUserType(randomEle(UserTypeEnum.values()).getValue());  
193 - o.setToken(token);  
194 - });  
195 - userSessionMapper.insert(userSession);  
196 -  
197 - // 调用  
198 - userSessionService.refreshUserSession(token, loginUser);  
199 - // 校验 LoginUser 缓存  
200 - LoginUser redisLoginUser = loginUserRedisDAO.get(token);  
201 - assertPojoEquals(redisLoginUser, loginUser, "username", "password");  
202 - // 校验 UserSessionDO 记录  
203 - UserSessionDO updateDO = userSessionMapper.selectOne(UserSessionDO::getToken, token);  
204 -// assertEquals(updateDO.getUsername(), loginUser.getUsername());  
205 - assertNotNull(userSession.getUpdateTime());  
206 - assertNotNull(userSession.getSessionTimeout());  
207 - }  
208 -  
209 - @Test  
210 public void testDeleteUserSession_Token() { 99 public void testDeleteUserSession_Token() {
211 // 准备参数 100 // 准备参数
212 String token = randomString(); 101 String token = randomString();