mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-08-17 11:41:54 +08:00
去除 Spring Security 的 Member 的 loadUsername,使用自己定义的 login0 实现
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
### 请求 /login 接口 => 成功
|
||||
POST {{appApi}}/member/login
|
||||
POST {{appApi}}/member/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package cn.iocoder.yudao.module.member.convert.auth;
|
||||
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.framework.security.core.authentication.SpringSecurityUser;
|
||||
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
|
||||
import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
@@ -11,7 +10,6 @@ import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
@@ -21,11 +19,6 @@ public interface AuthConvert {
|
||||
|
||||
LoginUser convert(MemberUserDO bean);
|
||||
|
||||
@Mapping(source = "mobile", target = "username")
|
||||
SpringSecurityUser convert2(MemberUserDO user);
|
||||
|
||||
LoginUser convert(SpringSecurityUser bean);
|
||||
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialBindLoginReqVO reqVO);
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialQuickLoginReqVO reqVO);
|
||||
SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppSocialUserUnbindReqVO reqVO);
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.member.service.auth;
|
||||
|
||||
import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
|
||||
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
@@ -12,7 +11,7 @@ import javax.validation.Valid;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface MemberAuthService extends SecurityAuthFrameworkService {
|
||||
public interface MemberAuthService {
|
||||
|
||||
/**
|
||||
* 手机 + 密码登录
|
||||
|
@@ -1,11 +1,12 @@
|
||||
package cn.iocoder.yudao.module.member.service.auth;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
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.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken;
|
||||
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
|
||||
import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
@@ -21,14 +22,6 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -49,10 +42,6 @@ import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
|
||||
@Slf4j
|
||||
public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,因为存在相互依赖的问题
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Resource
|
||||
private MemberUserService userService;
|
||||
@Resource
|
||||
@@ -69,17 +58,6 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
@Resource
|
||||
private MemberUserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
|
||||
// 获取 username 对应的 SysUserDO
|
||||
MemberUserDO user = userService.getUserByMobile(mobile);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(mobile);
|
||||
}
|
||||
// 创建 LoginUser 对象
|
||||
return AuthConvert.INSTANCE.convert2(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String login(AppAuthLoginReqVO reqVO, String userIp, String userAgent) {
|
||||
// 使用手机 + 密码,进行登录。
|
||||
@@ -157,43 +135,34 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
return socialUserApi.getAuthorizeUrl(type, redirectUri);
|
||||
}
|
||||
|
||||
private LoginUser login0(String username, String password) {
|
||||
final LoginLogTypeEnum logType = LoginLogTypeEnum.LOGIN_USERNAME;
|
||||
// 用户验证
|
||||
Authentication authentication;
|
||||
try {
|
||||
// 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证
|
||||
// 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
|
||||
authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken(
|
||||
username, password, getUserType()));
|
||||
} catch (BadCredentialsException badCredentialsException) {
|
||||
this.createLoginLog(null, username, logType, LoginResultEnum.BAD_CREDENTIALS);
|
||||
private LoginUser login0(String mobile, String password) {
|
||||
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE;
|
||||
// 校验账号是否存在
|
||||
MemberUserDO user = userService.getUserByMobile(mobile);
|
||||
if (user == null) {
|
||||
createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
} catch (DisabledException disabledException) {
|
||||
this.createLoginLog(null, username, logType, LoginResultEnum.USER_DISABLED);
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
} catch (AuthenticationException authenticationException) {
|
||||
log.error("[login0][username({}) 发生未知异常]", username, authenticationException);
|
||||
this.createLoginLog(null, username, logType, LoginResultEnum.UNKNOWN_ERROR);
|
||||
throw exception(AUTH_LOGIN_FAIL_UNKNOWN);
|
||||
}
|
||||
Assert.notNull(authentication.getPrincipal(), "Principal 不会为空");
|
||||
return (LoginUser) authentication.getPrincipal();
|
||||
if (!userService.isPasswordMatch(password, user.getPassword())) {
|
||||
createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
// 校验是否禁用
|
||||
if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
|
||||
createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED);
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
|
||||
// 构建 User 对象
|
||||
return buildLoginUser(user);
|
||||
}
|
||||
|
||||
private void createLoginLog(Long userId, String mobile, LoginLogTypeEnum logType, LoginResultEnum loginResult) {
|
||||
// 获得用户
|
||||
if (userId == null) {
|
||||
MemberUserDO user = userService.getUserByMobile(mobile);
|
||||
userId = user != null ? user.getId() : null;
|
||||
}
|
||||
// 插入登录日志
|
||||
LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
|
||||
reqDTO.setLogType(logType.getType());
|
||||
reqDTO.setTraceId(TracerUtils.getTraceId());
|
||||
if (userId != null) {
|
||||
reqDTO.setUserId(userId);
|
||||
}
|
||||
reqDTO.setUserId(userId);
|
||||
reqDTO.setUserType(getUserType().getValue());
|
||||
reqDTO.setUsername(mobile);
|
||||
reqDTO.setUserAgent(ServletUtils.getUserAgent());
|
||||
@@ -206,11 +175,6 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginUser verifyTokenAndRefresh(String token) {
|
||||
return userSessionApi.getLoginUser(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(String token) {
|
||||
// 查询用户信息
|
||||
@@ -224,17 +188,13 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
createLogoutLog(loginUser.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserTypeEnum getUserType() {
|
||||
return UserTypeEnum.MEMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePassword(Long userId, AppAuthUpdatePasswordReqVO reqVO) {
|
||||
// 检验旧密码
|
||||
MemberUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
|
||||
|
||||
// 更新用户密码
|
||||
// TODO 芋艿:需要重构到用户模块
|
||||
userMapper.updateById(MemberUserDO.builder().id(userDO.getId())
|
||||
.password(passwordEncoder.encode(reqVO.getPassword())).build());
|
||||
}
|
||||
@@ -312,4 +272,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
return user != null ? user.getMobile() : null;
|
||||
}
|
||||
|
||||
private UserTypeEnum getUserType() {
|
||||
return UserTypeEnum.MEMBER;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -69,4 +69,13 @@ public interface MemberUserService {
|
||||
*/
|
||||
void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 判断密码是否匹配
|
||||
*
|
||||
* @param rawPassword 未加密的密码
|
||||
* @param encodedPassword 加密后的密码
|
||||
* @return 是否匹配
|
||||
*/
|
||||
boolean isPasswordMatch(String rawPassword, String encodedPassword);
|
||||
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
MemberUserDO user = new MemberUserDO();
|
||||
user.setMobile(mobile);
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
|
||||
user.setPassword(passwordEncoder.encode(password)); // 加密密码
|
||||
user.setPassword(encodePassword(password)); // 加密密码
|
||||
user.setRegisterIp(registerIp);
|
||||
memberUserMapper.insert(user);
|
||||
return user;
|
||||
@@ -127,6 +127,21 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public MemberUserDO checkUserExists(Long id) {
|
||||
if (id == null) {
|
||||
|
@@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
|
||||
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.crypto.password.PasswordEncoder;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -38,8 +37,8 @@ import static org.mockito.Mockito.when;
|
||||
@Import({MemberAuthServiceImpl.class, YudaoRedisAutoConfiguration.class})
|
||||
public class MemberAuthServiceTest extends BaseDbAndRedisUnitTest {
|
||||
|
||||
@MockBean
|
||||
private AuthenticationManager authenticationManager;
|
||||
// TODO @芋艿:登录相关的单测,待补全
|
||||
|
||||
@MockBean
|
||||
private MemberUserService userService;
|
||||
@MockBean
|
||||
|
Reference in New Issue
Block a user