mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	去除 Spring Security 的 Admin 的 loadUsername,使用自己定义的 login0 实现
This commit is contained in:
		| @@ -26,8 +26,6 @@ public interface AuthConvert { | ||||
|  | ||||
|     SpringSecurityUser convert2(AdminUserDO user); | ||||
|  | ||||
|     LoginUser convert(SpringSecurityUser bean); | ||||
|  | ||||
|     default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) { | ||||
|         return AuthPermissionInfoRespVO.builder() | ||||
|             .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| package cn.iocoder.yudao.module.system.service.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; | ||||
| import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; | ||||
| import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; | ||||
|  | ||||
| import javax.validation.Valid; | ||||
|  | ||||
| /** | ||||
|  * 管理后台的认证 Service 接口 | ||||
|  * | ||||
|  * 提供用户的账号密码登录、token 的校验等认证相关的功能 | ||||
|  * 提供用户的登录、登出的能力 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @@ -24,6 +24,13 @@ public interface AdminAuthService extends SecurityAuthFrameworkService { | ||||
|      */ | ||||
|     String login(@Valid AuthLoginReqVO reqVO, String userIp, String userAgent); | ||||
|  | ||||
|     /** | ||||
|      * 基于 token 退出登录 | ||||
|      * | ||||
|      * @param token token | ||||
|      */ | ||||
|     void logout(String token); | ||||
|  | ||||
|     /** | ||||
|      * 短信验证码发送 | ||||
|      * | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| package cn.iocoder.yudao.module.system.service.auth; | ||||
|  | ||||
| import cn.hutool.core.util.ObjectUtil; | ||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||
| import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; | ||||
| import cn.iocoder.yudao.framework.security.core.LoginUser; | ||||
| import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken; | ||||
| import cn.iocoder.yudao.framework.security.core.authentication.SpringSecurityUser; | ||||
| import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; | ||||
| import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; | ||||
| import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; | ||||
| @@ -19,18 +19,11 @@ import cn.iocoder.yudao.module.system.service.common.CaptchaService; | ||||
| import cn.iocoder.yudao.module.system.service.logger.LoginLogService; | ||||
| import cn.iocoder.yudao.module.system.service.social.SocialUserService; | ||||
| import cn.iocoder.yudao.module.system.service.user.AdminUserService; | ||||
| import com.google.common.annotations.VisibleForTesting; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.context.annotation.Lazy; | ||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||
| import org.springframework.security.authentication.BadCredentialsException; | ||||
| import org.springframework.security.authentication.DisabledException; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.core.AuthenticationException; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | ||||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.util.Assert; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import javax.validation.Validator; | ||||
| @@ -50,11 +43,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||||
| public class AdminAuthServiceImpl implements AdminAuthService { | ||||
|  | ||||
|     @Resource | ||||
|     @Lazy // 延迟加载,因为存在相互依赖的问题 | ||||
|     private AuthenticationManager authenticationManager; | ||||
|  | ||||
|     @Autowired | ||||
|     @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // UserService 存在重名 | ||||
|     private AdminUserService userService; | ||||
|     @Resource | ||||
|     private CaptchaService captchaService; | ||||
| @@ -71,17 +59,6 @@ public class AdminAuthServiceImpl implements AdminAuthService { | ||||
|     @Resource | ||||
|     private SmsCodeApi smsCodeApi; | ||||
|  | ||||
|     @Override | ||||
|     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||||
|         // 获取 username 对应的 AdminUserDO | ||||
|         AdminUserDO user = userService.getUserByUsername(username); | ||||
|         if (user == null) { | ||||
|             throw new UsernameNotFoundException(username); | ||||
|         } | ||||
|         // 创建 LoginUser 对象 | ||||
|         return AuthConvert.INSTANCE.convert2(user); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String login(AuthLoginReqVO reqVO, String userIp, String userAgent) { | ||||
|         // 判断验证码是否正确 | ||||
| @@ -124,7 +101,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { | ||||
|                 LoginLogTypeEnum.LOGIN_MOBILE, userIp, userAgent); | ||||
|     } | ||||
|  | ||||
|     private void verifyCaptcha(AuthLoginReqVO reqVO) { | ||||
|     @VisibleForTesting | ||||
|     void verifyCaptcha(AuthLoginReqVO reqVO) { | ||||
|         // 如果验证码关闭,则不进行校验 | ||||
|         if (!captchaService.isCaptchaEnable()) { | ||||
|             return; | ||||
| @@ -149,46 +127,36 @@ public class AdminAuthServiceImpl implements AdminAuthService { | ||||
|         captchaService.deleteCaptchaCode(reqVO.getUuid()); | ||||
|     } | ||||
|  | ||||
|     private LoginUser login0(String username, String password) { | ||||
|     @VisibleForTesting | ||||
|     LoginUser login0(String username, String password) { | ||||
|         final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; | ||||
|         // 用户验证 | ||||
|         Authentication authentication; | ||||
|         try { | ||||
|             // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证 | ||||
|             // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 | ||||
|             authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken( | ||||
|                     username, password, getUserType())); | ||||
|         } catch (BadCredentialsException badCredentialsException) { | ||||
|         // 校验账号是否存在 | ||||
|         AdminUserDO user = userService.getUserByUsername(username); | ||||
|         if (user == null) { | ||||
|             createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); | ||||
|             throw exception(AUTH_LOGIN_BAD_CREDENTIALS); | ||||
|         } catch (DisabledException disabledException) { | ||||
|             createLoginLog(null, username, logTypeEnum, LoginResultEnum.USER_DISABLED); | ||||
|             throw exception(AUTH_LOGIN_USER_DISABLED); | ||||
|         } catch (AuthenticationException authenticationException) { | ||||
|             log.error("[login0][username({}) 发生未知异常]", username, authenticationException); | ||||
|             createLoginLog(null, username, logTypeEnum, LoginResultEnum.UNKNOWN_ERROR); | ||||
|             throw exception(AUTH_LOGIN_FAIL_UNKNOWN); | ||||
|         } | ||||
|         Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); | ||||
|         if (!userService.isPasswordMatch(password, user.getPassword())) { | ||||
|             createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); | ||||
|             throw exception(AUTH_LOGIN_BAD_CREDENTIALS); | ||||
|         } | ||||
|         // 校验是否禁用 | ||||
|         if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { | ||||
|             createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED); | ||||
|             throw exception(AUTH_LOGIN_USER_DISABLED); | ||||
|         } | ||||
|  | ||||
|         // 构建 User 对象 | ||||
|         return AuthConvert.INSTANCE.convert((SpringSecurityUser) authentication.getPrincipal()) | ||||
|                 .setUserType(getUserType().getValue()); | ||||
|         return buildLoginUser(user); | ||||
|     } | ||||
|  | ||||
|     private void createLoginLog(Long userId, String username, | ||||
|                                 LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) { | ||||
|         // 获得用户 | ||||
|         if (userId == null) { | ||||
|             AdminUserDO user = userService.getUserByUsername(username); | ||||
|             userId = user != null ? user.getId() : null; | ||||
|         } | ||||
|         // 插入登录日志 | ||||
|         LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); | ||||
|         reqDTO.setLogType(logTypeEnum.getType()); | ||||
|         reqDTO.setTraceId(TracerUtils.getTraceId()); | ||||
|         if (userId != null) { | ||||
|             reqDTO.setUserId(userId); | ||||
|         } | ||||
|         reqDTO.setUserId(userId); | ||||
|         reqDTO.setUserType(getUserType().getValue()); | ||||
|         reqDTO.setUsername(username); | ||||
|         reqDTO.setUserAgent(ServletUtils.getUserAgent()); | ||||
| @@ -293,4 +261,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { | ||||
|         return user != null ? user.getUsername() : null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -105,7 +105,6 @@ public interface AdminUserService { | ||||
|      */ | ||||
|     AdminUserDO getUserByMobile(String mobile); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 获得用户分页列表 | ||||
|      * | ||||
| @@ -209,4 +208,13 @@ public interface AdminUserService { | ||||
|      */ | ||||
|     List<AdminUserDO> getUsersByStatus(Integer status); | ||||
|  | ||||
|     /** | ||||
|      * 判断密码是否匹配 | ||||
|      * | ||||
|      * @param rawPassword 未加密的密码 | ||||
|      * @param encodedPassword 加密后的密码 | ||||
|      * @return 是否匹配 | ||||
|      */ | ||||
|     boolean isPasswordMatch(String rawPassword, String encodedPassword); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -148,7 +148,7 @@ public class AdminUserServiceImpl implements AdminUserService { | ||||
|         checkOldPassword(id, reqVO.getOldPassword()); | ||||
|         // 执行更新 | ||||
|         AdminUserDO updateObj = new AdminUserDO().setId(id); | ||||
|         updateObj.setPassword(passwordEncoder.encode(reqVO.getNewPassword())); // 加密密码 | ||||
|         updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码 | ||||
|         userMapper.updateById(updateObj); | ||||
|     } | ||||
|  | ||||
| @@ -172,7 +172,7 @@ public class AdminUserServiceImpl implements AdminUserService { | ||||
|         // 更新密码 | ||||
|         AdminUserDO updateObj = new AdminUserDO(); | ||||
|         updateObj.setId(id); | ||||
|         updateObj.setPassword(passwordEncoder.encode(password)); // 加密密码 | ||||
|         updateObj.setPassword(encodePassword(password)); // 加密密码 | ||||
|         userMapper.updateById(updateObj); | ||||
|     } | ||||
|  | ||||
| @@ -205,11 +205,6 @@ public class AdminUserServiceImpl implements AdminUserService { | ||||
|         return userMapper.selectByUsername(username); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 通过手机号获取用户 | ||||
|      * @param mobile | ||||
|      * @return | ||||
|      */ | ||||
|     @Override | ||||
|     public AdminUserDO getUserByMobile(String mobile) { | ||||
|         return userMapper.selectByMobile(mobile); | ||||
| @@ -395,7 +390,7 @@ public class AdminUserServiceImpl implements AdminUserService { | ||||
|         if (user == null) { | ||||
|             throw exception(USER_NOT_EXISTS); | ||||
|         } | ||||
|         if (!passwordEncoder.matches(oldPassword, user.getPassword())) { | ||||
|         if (!isPasswordMatch(oldPassword, user.getPassword())) { | ||||
|             throw exception(USER_PASSWORD_FAILED); | ||||
|         } | ||||
|     } | ||||
| @@ -421,7 +416,7 @@ public class AdminUserServiceImpl implements AdminUserService { | ||||
|             AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); | ||||
|             if (existUser == null) { | ||||
|                 userMapper.insert(UserConvert.INSTANCE.convert(importUser) | ||||
|                         .setPassword(passwordEncoder.encode(userInitPassword))); // 设置默认密码 | ||||
|                         .setPassword(encodePassword(userInitPassword))); // 设置默认密码 | ||||
|                 respVO.getCreateUsernames().add(importUser.getUsername()); | ||||
|                 return; | ||||
|             } | ||||
| @@ -443,4 +438,19 @@ public class AdminUserServiceImpl implements AdminUserService { | ||||
|         return userMapper.selectListByStatus(status); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean isPasswordMatch(String rawPassword, String encodedPassword) { | ||||
|         return passwordEncoder.matches(rawPassword, encodedPassword); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 对密码进行加密 | ||||
|      * | ||||
|      * @param password 密码 | ||||
|      * @return 加密后的密码 | ||||
|      */ | ||||
|     private String encodePassword(String password) { | ||||
|         return passwordEncoder.encode(password); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package cn.iocoder.yudao.module.system.service.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||
| import cn.iocoder.yudao.framework.security.core.LoginUser; | ||||
| import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||||
| import cn.iocoder.yudao.framework.test.core.util.AssertUtils; | ||||
| @@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | ||||
| import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; | ||||
| import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; | ||||
| import cn.iocoder.yudao.module.system.service.common.CaptchaService; | ||||
| import cn.iocoder.yudao.module.system.service.dept.PostService; | ||||
| import cn.iocoder.yudao.module.system.service.logger.LoginLogService; | ||||
| import cn.iocoder.yudao.module.system.service.social.SocialUserService; | ||||
| import cn.iocoder.yudao.module.system.service.user.AdminUserService; | ||||
| @@ -17,23 +17,16 @@ import org.junit.jupiter.api.BeforeEach; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.springframework.boot.test.mock.mockito.MockBean; | ||||
| import org.springframework.context.annotation.Import; | ||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||
| import org.springframework.security.authentication.BadCredentialsException; | ||||
| import org.springframework.security.authentication.DisabledException; | ||||
| import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.core.AuthenticationException; | ||||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import javax.validation.Validator; | ||||
| import java.util.Set; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; | ||||
| import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||||
| import static org.mockito.ArgumentMatchers.eq; | ||||
| import static org.mockito.Mockito.*; | ||||
|  | ||||
| @@ -46,10 +39,6 @@ public class AuthServiceImplTest extends BaseDbUnitTest { | ||||
|     @MockBean | ||||
|     private AdminUserService userService; | ||||
|     @MockBean | ||||
|     private AuthenticationManager authenticationManager; | ||||
|     @MockBean | ||||
|     private Authentication authentication; | ||||
|     @MockBean | ||||
|     private CaptchaService captchaService; | ||||
|     @MockBean | ||||
|     private LoginLogService loginLogService; | ||||
| @@ -58,8 +47,6 @@ public class AuthServiceImplTest extends BaseDbUnitTest { | ||||
|     @MockBean | ||||
|     private SocialUserService socialService; | ||||
|     @MockBean | ||||
|     private PostService postService; | ||||
|     @MockBean | ||||
|     private SmsCodeApi smsCodeApi; | ||||
|  | ||||
|     @MockBean | ||||
| @@ -71,40 +58,102 @@ public class AuthServiceImplTest extends BaseDbUnitTest { | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLoadUserByUsername_success() { | ||||
|     public void testLogin0_success() { | ||||
|         // 准备参数 | ||||
|         String username = randomString(); | ||||
|         // mock 方法 | ||||
|         AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username)); | ||||
|         String password = randomString(); | ||||
|         // mock user 数据 | ||||
|         AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username) | ||||
|                 .setPassword(password).setStatus(CommonStatusEnum.ENABLE.getStatus())); | ||||
|         when(userService.getUserByUsername(eq(username))).thenReturn(user); | ||||
|         // mock password 匹配 | ||||
|         when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true); | ||||
|  | ||||
|         // 调用 | ||||
|         LoginUser loginUser = (LoginUser) authService.loadUserByUsername(username); | ||||
|         LoginUser loginUser = authService.login0(username, password); | ||||
|         // 校验 | ||||
|         AssertUtils.assertPojoEquals(user, loginUser, "updateTime"); | ||||
|         assertPojoEquals(user, loginUser); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLoadUserByUsername_userNotFound() { | ||||
|     public void testLogin0_userNotFound() { | ||||
|         // 准备参数 | ||||
|         String username = randomString(); | ||||
|         // mock 方法 | ||||
|         String password = randomString(); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertThrows(UsernameNotFoundException.class, // 抛出 UsernameNotFoundException 异常 | ||||
|                 () -> authService.loadUserByUsername(username), | ||||
|                 username); // 异常提示为 username | ||||
|         AssertUtils.assertServiceException(() -> authService.login0(username, password), | ||||
|                 AUTH_LOGIN_BAD_CREDENTIALS); | ||||
|         verify(loginLogService).createLoginLog( | ||||
|                 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                         && o.getResult().equals(LoginResultEnum.BAD_CREDENTIALS.getResult()) | ||||
|                         && o.getUserId() == null) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin_captchaNotFound() { | ||||
|     public void testLogin0_badCredentials() { | ||||
|         // 准备参数 | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|         String userIp = randomString(); | ||||
|         String userAgent = randomString(); | ||||
|         String username = randomString(); | ||||
|         String password = randomString(); | ||||
|         // mock user 数据 | ||||
|         AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username) | ||||
|                 .setPassword(password).setStatus(CommonStatusEnum.ENABLE.getStatus())); | ||||
|         when(userService.getUserByUsername(eq(username))).thenReturn(user); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_NOT_FOUND); | ||||
|         AssertUtils.assertServiceException(() -> authService.login0(username, password), | ||||
|                 AUTH_LOGIN_BAD_CREDENTIALS); | ||||
|         verify(loginLogService).createLoginLog( | ||||
|                 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                         && o.getResult().equals(LoginResultEnum.BAD_CREDENTIALS.getResult()) | ||||
|                         && o.getUserId().equals(user.getId())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin0_userDisabled() { | ||||
|         // 准备参数 | ||||
|         String username = randomString(); | ||||
|         String password = randomString(); | ||||
|         // mock user 数据 | ||||
|         AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username) | ||||
|                 .setPassword(password).setStatus(CommonStatusEnum.DISABLE.getStatus())); | ||||
|         when(userService.getUserByUsername(eq(username))).thenReturn(user); | ||||
|         // mock password 匹配 | ||||
|         when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         AssertUtils.assertServiceException(() -> authService.login0(username, password), | ||||
|                 AUTH_LOGIN_USER_DISABLED); | ||||
|         verify(loginLogService).createLoginLog( | ||||
|                 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                         && o.getResult().equals(LoginResultEnum.USER_DISABLED.getResult()) | ||||
|                         && o.getUserId().equals(user.getId())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testCaptcha_success() { | ||||
|         // 准备参数 | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|  | ||||
|         // mock 验证码正确 | ||||
|         when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); | ||||
|  | ||||
|         // 调用 | ||||
|         authService.verifyCaptcha(reqVO); | ||||
|         // 断言 | ||||
|         verify(captchaService).deleteCaptchaCode(reqVO.getUuid()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testCaptcha_notFound() { | ||||
|         // 准备参数 | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> authService.verifyCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_NOT_FOUND); | ||||
|         // 校验调用参数 | ||||
|         verify(loginLogService, times(1)).createLoginLog( | ||||
|             argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
| @@ -113,10 +162,8 @@ public class AuthServiceImplTest extends BaseDbUnitTest { | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin_captchaCodeError() { | ||||
|     public void testCaptcha_codeError() { | ||||
|         // 准备参数 | ||||
|         String userIp = randomString(); | ||||
|         String userAgent = randomString(); | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|  | ||||
|         // mock 验证码不正确 | ||||
| @@ -124,109 +171,45 @@ public class AuthServiceImplTest extends BaseDbUnitTest { | ||||
|         when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(code); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_CODE_ERROR); | ||||
|         assertServiceException(() -> authService.verifyCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_CODE_ERROR); | ||||
|         // 校验调用参数 | ||||
|         verify(loginLogService, times(1)).createLoginLog( | ||||
|         verify(loginLogService).createLoginLog( | ||||
|             argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                     && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin_badCredentials() { | ||||
|         // 准备参数 | ||||
|         String userIp = randomString(); | ||||
|         String userAgent = randomString(); | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|         // mock 验证码正确 | ||||
|         when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); | ||||
|         // mock 抛出异常 | ||||
|         when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword()))) | ||||
|                 .thenThrow(new BadCredentialsException("测试账号或密码不正确")); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_BAD_CREDENTIALS); | ||||
|         // 校验调用参数 | ||||
|         verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); | ||||
|         verify(loginLogService, times(1)).createLoginLog( | ||||
|             argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                     && o.getResult().equals(LoginResultEnum.BAD_CREDENTIALS.getResult())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin_userDisabled() { | ||||
|         // 准备参数 | ||||
|         String userIp = randomString(); | ||||
|         String userAgent = randomString(); | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|  | ||||
|         // mock 验证码正确 | ||||
|         when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); | ||||
|         // mock 抛出异常 | ||||
|         when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword()))) | ||||
|                 .thenThrow(new DisabledException("测试用户被禁用")); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_USER_DISABLED); | ||||
|         // 校验调用参数 | ||||
|         verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); | ||||
|         verify(loginLogService, times(1)).createLoginLog( | ||||
|             argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                     && o.getResult().equals(LoginResultEnum.USER_DISABLED.getResult())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin_unknownError() { | ||||
|         // 准备参数 | ||||
|         String userIp = randomString(); | ||||
|         String userAgent = randomString(); | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|         // mock 验证码正确 | ||||
|         when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); | ||||
|         // mock 抛出异常 | ||||
|         when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword()))) | ||||
|                 .thenThrow(new AuthenticationException("测试未知异常") {}); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_FAIL_UNKNOWN); | ||||
|         // 校验调用参数 | ||||
|         verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); | ||||
|         verify(loginLogService, times(1)).createLoginLog( | ||||
|             argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                     && o.getResult().equals(LoginResultEnum.UNKNOWN_ERROR.getResult())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testLogin_success() { | ||||
|         // 准备参数 | ||||
|         String userIp = randomString(); | ||||
|         String userAgent = randomString(); | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); | ||||
|         AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o -> | ||||
|                 o.setUsername("test_username").setPassword("test_password")); | ||||
|  | ||||
|         // mock 验证码正确 | ||||
|         when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); | ||||
|         // mock authentication | ||||
|         Long userId = randomLongId(); | ||||
|         Set<Long> userRoleIds = randomSet(Long.class); | ||||
|         LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(userId)); | ||||
|         when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword()))) | ||||
|                 .thenReturn(authentication); | ||||
|         when(authentication.getPrincipal()).thenReturn(loginUser); | ||||
|         // mock user 数据 | ||||
|         AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername("test_username") | ||||
|                 .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus())); | ||||
|         when(userService.getUserByUsername(eq("test_username"))).thenReturn(user); | ||||
|         // mock password 匹配 | ||||
|         when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true); | ||||
|         // mock 缓存登录用户到 Redis | ||||
|         String token = randomString(); | ||||
|         when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(token); | ||||
|         when(userSessionService.createUserSession(argThat(argument -> { | ||||
|             AssertUtils.assertPojoEquals(user, argument); | ||||
|             return true; | ||||
|         }), eq(userIp), eq(userAgent))).thenReturn(token); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         String login = authService.login(reqVO, userIp, userAgent); | ||||
|         assertEquals(token, login); | ||||
|         String result = authService.login(reqVO, userIp, userAgent); | ||||
|         assertEquals(token, result); | ||||
|         // 校验调用参数 | ||||
|         verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); | ||||
|         verify(loginLogService, times(1)).createLoginLog( | ||||
|         verify(loginLogService).createLoginLog( | ||||
|             argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) | ||||
|                     && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())) | ||||
|                     && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()) | ||||
|                     && o.getUserId().equals(user.getId())) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV