Commit 5e8648508e11fa7fd72066396078944c24a18669

Authored by YunaiV
1 parent 3bd7e8e6

去除 Spring Security 的 Member 的 loadUsername,使用自己定义的 login0 实现

Showing 17 changed files with 62 additions and 382 deletions
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.security.config;
2 2  
3 3 import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
4   -import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
5 4 import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
6 5 import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
7 6 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
8 7 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
9   -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
10   -import cn.iocoder.yudao.framework.web.config.WebProperties;
11 8 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
12 9 import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
13 10 import org.springframework.boot.context.properties.EnableConfigurationProperties;
... ... @@ -20,7 +17,6 @@ import org.springframework.security.web.AuthenticationEntryPoint;
20 17 import org.springframework.security.web.access.AccessDeniedHandler;
21 18  
22 19 import javax.annotation.Resource;
23   -import java.util.List;
24 20  
25 21 /**
26 22 * Spring Security 自动配置类,主要用于相关组件的配置
... ... @@ -76,19 +72,8 @@ public class YudaoSecurityAutoConfiguration {
76 72 * Token 认证过滤器 Bean
77 73 */
78 74 @Bean
79   - public TokenAuthenticationFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider,
80   - GlobalExceptionHandler globalExceptionHandler) {
81   - return new TokenAuthenticationFilter(securityProperties, authenticationProvider, globalExceptionHandler);
82   - }
83   -
84   - /**
85   - * 身份验证的 Provider Bean,通过它实现账号 + 密码的认证
86   - */
87   - @Bean
88   - public MultiUserDetailsAuthenticationProvider authenticationProvider(
89   - List<SecurityAuthFrameworkService> securityFrameworkServices,
90   - WebProperties webProperties, PasswordEncoder passwordEncoder) {
91   - return new MultiUserDetailsAuthenticationProvider(securityFrameworkServices, webProperties, passwordEncoder);
  75 + public TokenAuthenticationFilter authenticationTokenFilter(GlobalExceptionHandler globalExceptionHandler) {
  76 + return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler);
92 77 }
93 78  
94 79 /**
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
1 1 package cn.iocoder.yudao.framework.security.config;
2 2  
3   -import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
4 3 import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
5 4 import cn.iocoder.yudao.framework.web.config.WebProperties;
6 5 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
... ... @@ -8,7 +7,6 @@ import org.springframework.context.annotation.Bean;
8 7 import org.springframework.context.annotation.Configuration;
9 8 import org.springframework.http.HttpMethod;
10 9 import org.springframework.security.authentication.AuthenticationManager;
11   -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
12 10 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
13 11 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
14 12 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
... ... @@ -32,8 +30,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
32 30 @Resource
33 31 private WebProperties webProperties;
34 32  
35   - @Resource
36   - private MultiUserDetailsAuthenticationProvider authenticationProvider;
37 33 /**
38 34 * 认证失败处理类 Bean
39 35 */
... ... @@ -70,14 +66,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
70 66 }
71 67  
72 68 /**
73   - * 身份认证接口
74   - */
75   - @Override
76   - protected void configure(AuthenticationManagerBuilder auth) throws Exception {
77   - auth.authenticationProvider(authenticationProvider);
78   - }
79   -
80   - /**
81 69 * 配置 URL 的安全配置
82 70 *
83 71 * anyRequest | 匹配所有请求路径
... ... @@ -130,11 +118,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
130 118 // 添加 JWT Filter
131 119 httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
132 120 }
133   -
134   - private String buildAdminApi(String url) {
135   - return webProperties.getAdminApi().getPrefix() + url;
136   - }
137   -
  121 +
138 122 private String buildAppApi(String url) {
139 123 return webProperties.getAppApi().getPrefix() + url;
140 124 }
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java deleted
1   -package cn.iocoder.yudao.framework.security.core.authentication;
2   -
3   -import cn.hutool.core.lang.Assert;
4   -import cn.hutool.core.util.StrUtil;
5   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6   -import cn.iocoder.yudao.framework.security.core.LoginUser;
7   -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
8   -import cn.iocoder.yudao.framework.web.config.WebProperties;
9   -import org.springframework.security.authentication.AuthenticationProvider;
10   -import org.springframework.security.authentication.BadCredentialsException;
11   -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
12   -import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
13   -import org.springframework.security.core.AuthenticationException;
14   -import org.springframework.security.core.userdetails.UserDetails;
15   -import org.springframework.security.crypto.password.PasswordEncoder;
16   -
17   -import javax.servlet.http.HttpServletRequest;
18   -import java.util.HashMap;
19   -import java.util.List;
20   -import java.util.Map;
21   -
22   -/**
23   - * 支持多用户类型的 AuthenticationProvider 实现类
24   - *
25   - * 为什么不用 {@link org.springframework.security.authentication.ProviderManager} 呢?
26   - * 原因是,需要每个用户类型实现对应的 {@link AuthenticationProvider} + authentication,略显麻烦。实际,也是可以实现的。
27   - *
28   - * 另外,额外支持 verifyTokenAndRefresh 校验令牌、logout 登出、mockLogin 模拟登陆等操作。
29   - * 实际上,它就是 {@link SecurityAuthFrameworkService} 定义的三个接口。
30   - * 因为需要支持多种类型,所以需要根据请求的 URL,判断出对应的用户类型,从而使用对应的 SecurityAuthFrameworkService 是吸纳
31   - *
32   - * @see cn.iocoder.yudao.framework.common.enums.UserTypeEnum
33   - * @author 芋道源码
34   - */
35   -public class MultiUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
36   -
37   - private final Map<UserTypeEnum, SecurityAuthFrameworkService> services = new HashMap<>();
38   -
39   - private final WebProperties properties;
40   -
41   - private final PasswordEncoder passwordEncoder;
42   -
43   - public MultiUserDetailsAuthenticationProvider(List<SecurityAuthFrameworkService> serviceList,
44   - WebProperties properties, PasswordEncoder passwordEncoder) {
45   - serviceList.forEach(service -> services.put(service.getUserType(), service));
46   - this.properties = properties;
47   - this.passwordEncoder = passwordEncoder;
48   - }
49   -
50   - // ========== AuthenticationProvider 相关 ==========
51   -
52   - @Override
53   - protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
54   - throws AuthenticationException {
55   - // 执行用户的加载
56   - return selectService(authentication).loadUserByUsername(username);
57   - }
58   -
59   - private SecurityAuthFrameworkService selectService(UsernamePasswordAuthenticationToken authentication) {
60   - // 第一步,获得用户类型
61   - UserTypeEnum userType = getUserType(authentication);
62   - // 第二步,获得 SecurityAuthFrameworkService
63   - SecurityAuthFrameworkService service = services.get(userType);
64   - Assert.notNull(service, "用户类型({}) 找不到 SecurityAuthFrameworkService 实现类", userType);
65   - return service;
66   - }
67   -
68   - private UserTypeEnum getUserType(UsernamePasswordAuthenticationToken authentication) {
69   - Assert.isInstanceOf(MultiUsernamePasswordAuthenticationToken.class, authentication);
70   - MultiUsernamePasswordAuthenticationToken multiAuthentication = (MultiUsernamePasswordAuthenticationToken) authentication;
71   - UserTypeEnum userType = multiAuthentication.getUserType();
72   - Assert.notNull(userType, "用户类型不能为空");
73   - return userType;
74   - }
75   -
76   - @Override // copy 自 DaoAuthenticationProvider 的 additionalAuthenticationChecks 方法
77   - protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
78   - throws AuthenticationException {
79   - // 校验 credentials
80   - if (authentication.getCredentials() == null) {
81   - this.logger.debug("Failed to authenticate since no credentials provided");
82   - throw new BadCredentialsException(this.messages.getMessage(
83   - "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
84   - }
85   - // 校验 password
86   - String presentedPassword = authentication.getCredentials().toString();
87   - if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
88   - this.logger.debug("Failed to authenticate since password does not match stored value");
89   - throw new BadCredentialsException(this.messages.getMessage(
90   - "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
91   - }
92   - }
93   -
94   - // ========== SecurityAuthFrameworkService 相关 ==========
95   -
96   - /**
97   - * 校验 token 的有效性,并获取用户信息
98   - * 通过后,刷新 token 的过期时间
99   - *
100   - * @param request 请求
101   - * @param token token
102   - * @return 用户信息
103   - */
104   - public LoginUser verifyTokenAndRefresh(HttpServletRequest request, String token) {
105   - return selectService(request).verifyTokenAndRefresh(token);
106   - }
107   -
108   - private SecurityAuthFrameworkService selectService(HttpServletRequest request) {
109   - // 第一步,获得用户类型
110   - UserTypeEnum userType = getUserType(request);
111   - // 第二步,获得 SecurityAuthFrameworkService
112   - SecurityAuthFrameworkService service = services.get(userType);
113   - Assert.notNull(service, "URI({}) 用户类型({}) 找不到 SecurityAuthFrameworkService 实现类",
114   - request.getRequestURI(), userType);
115   - return service;
116   - }
117   -
118   - private UserTypeEnum getUserType(HttpServletRequest request) {
119   - if (request.getRequestURI().startsWith(properties.getAdminApi().getPrefix())) {
120   - return UserTypeEnum.ADMIN;
121   - }
122   - if (request.getRequestURI().startsWith(properties.getAppApi().getPrefix())) {
123   - return UserTypeEnum.MEMBER;
124   - }
125   - throw new IllegalArgumentException(StrUtil.format("URI({}) 找不到匹配的用户类型", request.getRequestURI()));
126   - }
127   -
128   -}
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java deleted
1   -package cn.iocoder.yudao.framework.security.core.authentication;
2   -
3   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4   -import lombok.Getter;
5   -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6   -import org.springframework.security.core.GrantedAuthority;
7   -
8   -import java.util.Collection;
9   -
10   -/**
11   - * 支持多用户的 UsernamePasswordAuthenticationToken 实现类
12   - *
13   - * @author 芋道源码
14   - */
15   -@Getter
16   -public class MultiUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken {
17   -
18   - /**
19   - * 用户类型
20   - */
21   - private UserTypeEnum userType;
22   -
23   - public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials) {
24   - super(principal, credentials);
25   - }
26   -
27   - public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials,
28   - Collection<? extends GrantedAuthority> authorities) {
29   - super(principal, credentials, authorities);
30   - }
31   -
32   - public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials, UserTypeEnum userType) {
33   - super(principal, credentials);
34   - this.userType = userType;
35   - }
36   -
37   - public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials,
38   - Collection<? extends GrantedAuthority> authorities, UserTypeEnum userType) {
39   - super(principal, credentials, authorities);
40   - this.userType = userType;
41   - }
42   -
43   -}
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/SpringSecurityUser.java deleted
1   -package cn.iocoder.yudao.framework.security.core.authentication;
2   -
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import lombok.AllArgsConstructor;
5   -import lombok.Data;
6   -import org.springframework.security.core.GrantedAuthority;
7   -import org.springframework.security.core.userdetails.UserDetails;
8   -
9   -import java.util.Collection;
10   -import java.util.Collections;
11   -
12   -/**
13   - * 登录用户信息
14   - *
15   - * @author 芋道源码
16   - */
17   -@Data
18   -@AllArgsConstructor
19   -public class SpringSecurityUser implements UserDetails {
20   -
21   - /**
22   - * 用户编号
23   - */
24   - private Long id;
25   -
26   - /**
27   - * 用户名
28   - */
29   - private String username;
30   - /**
31   - * 密码
32   - */
33   - private String password;
34   - /**
35   - * 状态
36   - */
37   - private Integer status;
38   - /**
39   - * 租户编号
40   - */
41   - private Long tenantId;
42   -
43   - @Override
44   - public String getPassword() {
45   - return password;
46   - }
47   -
48   - @Override
49   - public String getUsername() {
50   - return username;
51   - }
52   -
53   - @Override
54   - public boolean isEnabled() {
55   - return CommonStatusEnum.ENABLE.getStatus().equals(status);
56   - }
57   -
58   - @Override
59   - public Collection<? extends GrantedAuthority> getAuthorities() {
60   - return Collections.emptyList();
61   - }
62   -
63   - @Override
64   - public boolean isAccountNonExpired() {
65   - return true; // 返回 true,不依赖 Spring Security 判断
66   - }
67   -
68   - @Override
69   - public boolean isAccountNonLocked() {
70   - return true; // 返回 true,不依赖 Spring Security 判断
71   - }
72   -
73   - @Override
74   - public boolean isCredentialsNonExpired() {
75   - return true; // 返回 true,不依赖 Spring Security 判断
76   - }
77   -
78   -}
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java
... ... @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 5 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
6 6 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
7 7 import cn.iocoder.yudao.framework.security.core.LoginUser;
8   -import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
9 8 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
10 9 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
11 10 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
... ... @@ -29,8 +28,6 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
29 28  
30 29 private final SecurityProperties securityProperties;
31 30  
32   - private final MultiUserDetailsAuthenticationProvider authenticationProvider;
33   -
34 31 private final GlobalExceptionHandler globalExceptionHandler;
35 32  
36 33 @Override
... ... @@ -42,7 +39,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
42 39 Integer userType = WebFrameworkUtils.getLoginUserType(request);
43 40 try {
44 41 // 验证 token 有效性
45   - LoginUser loginUser = authenticationProvider.verifyTokenAndRefresh(request, token);
  42 + LoginUser loginUser = null; // TODO 芋艿:待实现
46 43 // 模拟 Login 功能,方便日常开发调试
47 44 if (loginUser == null) {
48 45 loginUser = mockLoginUser(request, token, userType);
... ...
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
... ... @@ -17,7 +17,6 @@ public interface ErrorCodeConstants {
17 17 // ========== AUTH 模块 1004003000 ==========
18 18 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");
19 19 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1004003001, "登录失败,账号被禁用");
20   - ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1004003002, "登录失败"); // 登录失败的兜底,未知原因
21 20 ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期");
22 21 ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定");
23 22  
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http
1 1 ### 请求 /login 接口 => 成功
2   -POST {{appApi}}/member/login
  2 +POST {{appApi}}/member/auth/login
3 3 Content-Type: application/json
4 4 tenant-id: {{appTenentId}}
5 5  
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java
1 1 package cn.iocoder.yudao.module.member.convert.auth;
2 2  
3 3 import cn.iocoder.yudao.framework.security.core.LoginUser;
4   -import cn.iocoder.yudao.framework.security.core.authentication.SpringSecurityUser;
5 4 import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
6 5 import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO;
7 6 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
... ... @@ -11,7 +10,6 @@ import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
11 10 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
12 11 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
13 12 import org.mapstruct.Mapper;
14   -import org.mapstruct.Mapping;
15 13 import org.mapstruct.factory.Mappers;
16 14  
17 15 @Mapper
... ... @@ -21,11 +19,6 @@ public interface AuthConvert {
21 19  
22 20 LoginUser convert(MemberUserDO bean);
23 21  
24   - @Mapping(source = "mobile", target = "username")
25   - SpringSecurityUser convert2(MemberUserDO user);
26   -
27   - LoginUser convert(SpringSecurityUser bean);
28   -
29 22 SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialBindLoginReqVO reqVO);
30 23 SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialQuickLoginReqVO reqVO);
31 24 SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppSocialUserUnbindReqVO reqVO);
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java
1 1 package cn.iocoder.yudao.module.member.service.auth;
2 2  
3   -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
4 3 import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
5 4  
6 5 import javax.validation.Valid;
... ... @@ -12,7 +11,7 @@ import javax.validation.Valid;
12 11 *
13 12 * @author 芋道源码
14 13 */
15   -public interface MemberAuthService extends SecurityAuthFrameworkService {
  14 +public interface MemberAuthService {
16 15  
17 16 /**
18 17 * 手机 + 密码登录
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
1 1 package cn.iocoder.yudao.module.member.service.auth;
2 2  
3 3 import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 6 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 7 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
6 8 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
7 9 import cn.iocoder.yudao.framework.security.core.LoginUser;
8   -import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken;
9 10 import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
10 11 import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
11 12 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
... ... @@ -21,14 +22,6 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
21 22 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
22 23 import com.google.common.annotations.VisibleForTesting;
23 24 import lombok.extern.slf4j.Slf4j;
24   -import org.springframework.context.annotation.Lazy;
25   -import org.springframework.security.authentication.AuthenticationManager;
26   -import org.springframework.security.authentication.BadCredentialsException;
27   -import org.springframework.security.authentication.DisabledException;
28   -import org.springframework.security.core.Authentication;
29   -import org.springframework.security.core.AuthenticationException;
30   -import org.springframework.security.core.userdetails.UserDetails;
31   -import org.springframework.security.core.userdetails.UsernameNotFoundException;
32 25 import org.springframework.security.crypto.password.PasswordEncoder;
33 26 import org.springframework.stereotype.Service;
34 27 import org.springframework.transaction.annotation.Transactional;
... ... @@ -50,10 +43,6 @@ import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
50 43 public class MemberAuthServiceImpl implements MemberAuthService {
51 44  
52 45 @Resource
53   - @Lazy // 延迟加载,因为存在相互依赖的问题
54   - private AuthenticationManager authenticationManager;
55   -
56   - @Resource
57 46 private MemberUserService userService;
58 47 @Resource
59 48 private SmsCodeApi smsCodeApi;
... ... @@ -70,17 +59,6 @@ public class MemberAuthServiceImpl implements MemberAuthService {
70 59 private MemberUserMapper userMapper;
71 60  
72 61 @Override
73   - public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
74   - // 获取 username 对应的 SysUserDO
75   - MemberUserDO user = userService.getUserByMobile(mobile);
76   - if (user == null) {
77   - throw new UsernameNotFoundException(mobile);
78   - }
79   - // 创建 LoginUser 对象
80   - return AuthConvert.INSTANCE.convert2(user);
81   - }
82   -
83   - @Override
84 62 public String login(AppAuthLoginReqVO reqVO, String userIp, String userAgent) {
85 63 // 使用手机 + 密码,进行登录。
86 64 LoginUser loginUser = login0(reqVO.getMobile(), reqVO.getPassword());
... ... @@ -157,43 +135,34 @@ public class MemberAuthServiceImpl implements MemberAuthService {
157 135 return socialUserApi.getAuthorizeUrl(type, redirectUri);
158 136 }
159 137  
160   - private LoginUser login0(String username, String password) {
161   - final LoginLogTypeEnum logType = LoginLogTypeEnum.LOGIN_USERNAME;
162   - // 用户验证
163   - Authentication authentication;
164   - try {
165   - // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证
166   - // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
167   - authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken(
168   - username, password, getUserType()));
169   - } catch (BadCredentialsException badCredentialsException) {
170   - this.createLoginLog(null, username, logType, LoginResultEnum.BAD_CREDENTIALS);
  138 + private LoginUser login0(String mobile, String password) {
  139 + final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE;
  140 + // 校验账号是否存在
  141 + MemberUserDO user = userService.getUserByMobile(mobile);
  142 + if (user == null) {
  143 + createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
171 144 throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
172   - } catch (DisabledException disabledException) {
173   - this.createLoginLog(null, username, logType, LoginResultEnum.USER_DISABLED);
  145 + }
  146 + if (!userService.isPasswordMatch(password, user.getPassword())) {
  147 + createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
  148 + throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
  149 + }
  150 + // 校验是否禁用
  151 + if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
  152 + createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED);
174 153 throw exception(AUTH_LOGIN_USER_DISABLED);
175   - } catch (AuthenticationException authenticationException) {
176   - log.error("[login0][username({}) 发生未知异常]", username, authenticationException);
177   - this.createLoginLog(null, username, logType, LoginResultEnum.UNKNOWN_ERROR);
178   - throw exception(AUTH_LOGIN_FAIL_UNKNOWN);
179 154 }
180   - Assert.notNull(authentication.getPrincipal(), "Principal 不会为空");
181   - return (LoginUser) authentication.getPrincipal();
  155 +
  156 + // 构建 User 对象
  157 + return buildLoginUser(user);
182 158 }
183 159  
184 160 private void createLoginLog(Long userId, String mobile, LoginLogTypeEnum logType, LoginResultEnum loginResult) {
185   - // 获得用户
186   - if (userId == null) {
187   - MemberUserDO user = userService.getUserByMobile(mobile);
188   - userId = user != null ? user.getId() : null;
189   - }
190 161 // 插入登录日志
191 162 LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
192 163 reqDTO.setLogType(logType.getType());
193 164 reqDTO.setTraceId(TracerUtils.getTraceId());
194   - if (userId != null) {
195   - reqDTO.setUserId(userId);
196   - }
  165 + reqDTO.setUserId(userId);
197 166 reqDTO.setUserType(getUserType().getValue());
198 167 reqDTO.setUsername(mobile);
199 168 reqDTO.setUserAgent(ServletUtils.getUserAgent());
... ... @@ -207,11 +176,6 @@ public class MemberAuthServiceImpl implements MemberAuthService {
207 176 }
208 177  
209 178 @Override
210   - public LoginUser verifyTokenAndRefresh(String token) {
211   - return userSessionApi.getLoginUser(token);
212   - }
213   -
214   - @Override
215 179 public void logout(String token) {
216 180 // 查询用户信息
217 181 LoginUser loginUser = userSessionApi.getLoginUser(token);
... ... @@ -225,16 +189,12 @@ public class MemberAuthServiceImpl implements MemberAuthService {
225 189 }
226 190  
227 191 @Override
228   - public UserTypeEnum getUserType() {
229   - return UserTypeEnum.MEMBER;
230   - }
231   -
232   - @Override
233 192 public void updatePassword(Long userId, AppAuthUpdatePasswordReqVO reqVO) {
234 193 // 检验旧密码
235 194 MemberUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
236 195  
237 196 // 更新用户密码
  197 + // TODO 芋艿:需要重构到用户模块
238 198 userMapper.updateById(MemberUserDO.builder().id(userDO.getId())
239 199 .password(passwordEncoder.encode(reqVO.getPassword())).build());
240 200 }
... ... @@ -312,4 +272,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
312 272 return user != null ? user.getMobile() : null;
313 273 }
314 274  
  275 + private UserTypeEnum getUserType() {
  276 + return UserTypeEnum.MEMBER;
  277 + }
  278 +
315 279 }
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
... ... @@ -69,4 +69,13 @@ public interface MemberUserService {
69 69 */
70 70 void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO);
71 71  
  72 + /**
  73 + * 判断密码是否匹配
  74 + *
  75 + * @param rawPassword 未加密的密码
  76 + * @param encodedPassword 加密后的密码
  77 + * @return 是否匹配
  78 + */
  79 + boolean isPasswordMatch(String rawPassword, String encodedPassword);
  80 +
72 81 }
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
... ... @@ -69,7 +69,7 @@ public class MemberUserServiceImpl implements MemberUserService {
69 69 MemberUserDO user = new MemberUserDO();
70 70 user.setMobile(mobile);
71 71 user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
72   - user.setPassword(passwordEncoder.encode(password)); // 加密密码
  72 + user.setPassword(encodePassword(password)); // 加密密码
73 73 user.setRegisterIp(registerIp);
74 74 memberUserMapper.insert(user);
75 75 return user;
... ... @@ -127,6 +127,21 @@ public class MemberUserServiceImpl implements MemberUserService {
127 127 memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
128 128 }
129 129  
  130 + @Override
  131 + public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
  132 + return passwordEncoder.matches(rawPassword, encodedPassword);
  133 + }
  134 +
  135 + /**
  136 + * 对密码进行加密
  137 + *
  138 + * @param password 密码
  139 + * @return 加密后的密码
  140 + */
  141 + private String encodePassword(String password) {
  142 + return passwordEncoder.encode(password);
  143 + }
  144 +
130 145 @VisibleForTesting
131 146 public MemberUserDO checkUserExists(Long id) {
132 147 if (id == null) {
... ...
yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java
... ... @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
16 16 import org.junit.jupiter.api.Test;
17 17 import org.springframework.boot.test.mock.mockito.MockBean;
18 18 import org.springframework.context.annotation.Import;
19   -import org.springframework.security.authentication.AuthenticationManager;
20 19 import org.springframework.security.crypto.password.PasswordEncoder;
21 20  
22 21 import javax.annotation.Resource;
... ... @@ -38,8 +37,8 @@ import static org.mockito.Mockito.when;
38 37 @Import({MemberAuthServiceImpl.class, YudaoRedisAutoConfiguration.class})
39 38 public class MemberAuthServiceTest extends BaseDbAndRedisUnitTest {
40 39  
41   - @MockBean
42   - private AuthenticationManager authenticationManager;
  40 + // TODO @芋艿:登录相关的单测,待补全
  41 +
43 42 @MockBean
44 43 private MemberUserService userService;
45 44 @MockBean
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
... ... @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.convert.auth;
2 2  
3 3 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 4 import cn.iocoder.yudao.framework.security.core.LoginUser;
5   -import cn.iocoder.yudao.framework.security.core.authentication.SpringSecurityUser;
6 5 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
7 6 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
8 7 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
... ... @@ -24,8 +23,6 @@ public interface AuthConvert {
24 23  
25 24 LoginUser convert(AdminUserDO bean);
26 25  
27   - SpringSecurityUser convert2(AdminUserDO user);
28   -
29 26 default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
30 27 return AuthPermissionInfoRespVO.builder()
31 28 .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build())
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
... ... @@ -12,7 +12,7 @@ import javax.validation.Valid;
12 12 *
13 13 * @author 芋道源码
14 14 */
15   -public interface AdminAuthService extends SecurityAuthFrameworkService {
  15 +public interface AdminAuthService {
16 16  
17 17 /**
18 18 * 账号登录
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
... ... @@ -21,8 +21,6 @@ import cn.iocoder.yudao.module.system.service.social.SocialUserService;
21 21 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
22 22 import com.google.common.annotations.VisibleForTesting;
23 23 import lombok.extern.slf4j.Slf4j;
24   -import org.springframework.security.core.userdetails.UserDetails;
25   -import org.springframework.security.core.userdetails.UsernameNotFoundException;
26 24 import org.springframework.stereotype.Service;
27 25  
28 26 import javax.annotation.Resource;
... ... @@ -226,11 +224,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
226 224 createLogoutLog(loginUser.getId());
227 225 }
228 226  
229   - @Override
230   - public UserTypeEnum getUserType() {
231   - return UserTypeEnum.ADMIN;
232   - }
233   -
234 227 private void createLogoutLog(Long userId) {
235 228 LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
236 229 reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_SELF.getType());
... ... @@ -244,11 +237,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
244 237 loginLogService.createLoginLog(reqDTO);
245 238 }
246 239  
247   - @Override
248   - public LoginUser verifyTokenAndRefresh(String token) {
249   - return userSessionService.getLoginUser(token);
250   - }
251   -
252 240 private LoginUser buildLoginUser(AdminUserDO user) {
253 241 return AuthConvert.INSTANCE.convert(user).setUserType(getUserType().getValue());
254 242 }
... ... @@ -261,8 +249,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
261 249 return user != null ? user.getUsername() : null;
262 250 }
263 251  
264   - @Override
265   - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
266   - return null;
  252 + private UserTypeEnum getUserType() {
  253 + return UserTypeEnum.ADMIN;
267 254 }
  255 +
268 256 }
... ...