Forráskód Böngészése

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

YunaiV 2 éve
szülő
commit
5e8648508e
17 módosított fájl, 62 hozzáadás és 382 törlés
  1. 2 17
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
  2. 1 17
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
  3. 0 128
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java
  4. 0 43
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java
  5. 0 78
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/SpringSecurityUser.java
  6. 1 4
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java
  7. 0 1
      yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
  8. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http
  9. 0 7
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java
  10. 1 2
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java
  11. 25 61
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
  12. 9 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
  13. 16 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
  14. 2 3
      yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java
  15. 0 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
  16. 1 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
  17. 3 15
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java

+ 2 - 17
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java

@@ -1,13 +1,10 @@
 package cn.iocoder.yudao.framework.security.config;
 
 import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
-import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
 import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
 import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
-import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
-import cn.iocoder.yudao.framework.web.config.WebProperties;
 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
 import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -20,7 +17,6 @@ import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.security.web.access.AccessDeniedHandler;
 
 import javax.annotation.Resource;
-import java.util.List;
 
 /**
  * Spring Security 自动配置类,主要用于相关组件的配置
@@ -76,19 +72,8 @@ public class YudaoSecurityAutoConfiguration {
      * Token 认证过滤器 Bean
      */
     @Bean
-    public TokenAuthenticationFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider,
-                                                               GlobalExceptionHandler globalExceptionHandler) {
-        return new TokenAuthenticationFilter(securityProperties, authenticationProvider, globalExceptionHandler);
-    }
-
-    /**
-     * 身份验证的 Provider Bean,通过它实现账号 + 密码的认证
-     */
-    @Bean
-    public MultiUserDetailsAuthenticationProvider authenticationProvider(
-            List<SecurityAuthFrameworkService> securityFrameworkServices,
-            WebProperties webProperties, PasswordEncoder passwordEncoder) {
-        return new MultiUserDetailsAuthenticationProvider(securityFrameworkServices, webProperties, passwordEncoder);
+    public TokenAuthenticationFilter authenticationTokenFilter(GlobalExceptionHandler globalExceptionHandler) {
+        return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler);
     }
 
     /**

+ 1 - 17
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.framework.security.config;
 
-import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
 import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
 import cn.iocoder.yudao.framework.web.config.WebProperties;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -8,7 +7,6 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.HttpMethod;
 import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@@ -32,8 +30,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
     @Resource
     private WebProperties webProperties;
 
-    @Resource
-    private MultiUserDetailsAuthenticationProvider authenticationProvider;
     /**
      * 认证失败处理类 Bean
      */
@@ -69,14 +65,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
         return super.authenticationManagerBean();
     }
 
-    /**
-     * 身份认证接口
-     */
-    @Override
-    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-        auth.authenticationProvider(authenticationProvider);
-    }
-
     /**
      * 配置 URL 的安全配置
      *
@@ -130,11 +118,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
         // 添加 JWT Filter
         httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
     }
-
-    private String buildAdminApi(String url) {
-        return webProperties.getAdminApi().getPrefix() + url;
-    }
-
+    
     private String buildAppApi(String url) {
         return webProperties.getAppApi().getPrefix() + url;
     }

+ 0 - 128
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java

@@ -1,128 +0,0 @@
-package cn.iocoder.yudao.framework.security.core.authentication;
-
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
-import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
-import cn.iocoder.yudao.framework.web.config.WebProperties;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 支持多用户类型的 AuthenticationProvider 实现类
- *
- * 为什么不用 {@link org.springframework.security.authentication.ProviderManager} 呢?
- * 原因是,需要每个用户类型实现对应的 {@link AuthenticationProvider} + authentication,略显麻烦。实际,也是可以实现的。
- *
- * 另外,额外支持 verifyTokenAndRefresh 校验令牌、logout 登出、mockLogin 模拟登陆等操作。
- * 实际上,它就是 {@link SecurityAuthFrameworkService} 定义的三个接口。
- * 因为需要支持多种类型,所以需要根据请求的 URL,判断出对应的用户类型,从而使用对应的 SecurityAuthFrameworkService 是吸纳
- *
- * @see cn.iocoder.yudao.framework.common.enums.UserTypeEnum
- * @author 芋道源码
- */
-public class MultiUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
-
-    private final Map<UserTypeEnum, SecurityAuthFrameworkService> services = new HashMap<>();
-
-    private final WebProperties properties;
-
-    private final PasswordEncoder passwordEncoder;
-
-    public MultiUserDetailsAuthenticationProvider(List<SecurityAuthFrameworkService> serviceList,
-                                                  WebProperties properties, PasswordEncoder passwordEncoder) {
-        serviceList.forEach(service -> services.put(service.getUserType(), service));
-        this.properties = properties;
-        this.passwordEncoder = passwordEncoder;
-    }
-
-    // ========== AuthenticationProvider 相关 ==========
-
-    @Override
-    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
-            throws AuthenticationException {
-        // 执行用户的加载
-        return selectService(authentication).loadUserByUsername(username);
-    }
-
-    private SecurityAuthFrameworkService selectService(UsernamePasswordAuthenticationToken authentication) {
-        // 第一步,获得用户类型
-        UserTypeEnum userType = getUserType(authentication);
-        // 第二步,获得 SecurityAuthFrameworkService
-        SecurityAuthFrameworkService service = services.get(userType);
-        Assert.notNull(service, "用户类型({}) 找不到 SecurityAuthFrameworkService 实现类", userType);
-        return service;
-    }
-
-    private UserTypeEnum getUserType(UsernamePasswordAuthenticationToken authentication) {
-        Assert.isInstanceOf(MultiUsernamePasswordAuthenticationToken.class, authentication);
-        MultiUsernamePasswordAuthenticationToken multiAuthentication = (MultiUsernamePasswordAuthenticationToken) authentication;
-        UserTypeEnum userType = multiAuthentication.getUserType();
-        Assert.notNull(userType, "用户类型不能为空");
-        return userType;
-    }
-
-    @Override // copy 自 DaoAuthenticationProvider 的 additionalAuthenticationChecks 方法
-    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
-            throws AuthenticationException {
-        // 校验 credentials
-        if (authentication.getCredentials() == null) {
-            this.logger.debug("Failed to authenticate since no credentials provided");
-            throw new BadCredentialsException(this.messages.getMessage(
-                    "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
-        }
-        // 校验 password
-        String presentedPassword = authentication.getCredentials().toString();
-        if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
-            this.logger.debug("Failed to authenticate since password does not match stored value");
-            throw new BadCredentialsException(this.messages.getMessage(
-                    "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
-        }
-    }
-
-    // ========== SecurityAuthFrameworkService 相关 ==========
-
-    /**
-     * 校验 token 的有效性,并获取用户信息
-     * 通过后,刷新 token 的过期时间
-     *
-     * @param request 请求
-     * @param token token
-     * @return 用户信息
-     */
-    public LoginUser verifyTokenAndRefresh(HttpServletRequest request, String token) {
-        return selectService(request).verifyTokenAndRefresh(token);
-    }
-
-    private SecurityAuthFrameworkService selectService(HttpServletRequest request) {
-        // 第一步,获得用户类型
-        UserTypeEnum userType = getUserType(request);
-        // 第二步,获得 SecurityAuthFrameworkService
-        SecurityAuthFrameworkService service = services.get(userType);
-        Assert.notNull(service, "URI({}) 用户类型({}) 找不到 SecurityAuthFrameworkService 实现类",
-                request.getRequestURI(), userType);
-        return service;
-    }
-
-    private UserTypeEnum getUserType(HttpServletRequest request) {
-        if (request.getRequestURI().startsWith(properties.getAdminApi().getPrefix())) {
-            return UserTypeEnum.ADMIN;
-        }
-        if (request.getRequestURI().startsWith(properties.getAppApi().getPrefix())) {
-            return UserTypeEnum.MEMBER;
-        }
-        throw new IllegalArgumentException(StrUtil.format("URI({}) 找不到匹配的用户类型", request.getRequestURI()));
-    }
-
-}

+ 0 - 43
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java

@@ -1,43 +0,0 @@
-package cn.iocoder.yudao.framework.security.core.authentication;
-
-import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
-import lombok.Getter;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.GrantedAuthority;
-
-import java.util.Collection;
-
-/**
- * 支持多用户的 UsernamePasswordAuthenticationToken 实现类
- *
- * @author 芋道源码
- */
-@Getter
-public class MultiUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken {
-
-    /**
-     * 用户类型
-     */
-    private UserTypeEnum userType;
-
-    public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials) {
-        super(principal, credentials);
-    }
-
-    public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials,
-                                                    Collection<? extends GrantedAuthority> authorities) {
-        super(principal, credentials, authorities);
-    }
-
-    public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials, UserTypeEnum userType) {
-        super(principal, credentials);
-        this.userType = userType;
-    }
-
-    public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials,
-                                                    Collection<? extends GrantedAuthority> authorities, UserTypeEnum userType) {
-        super(principal, credentials, authorities);
-        this.userType = userType;
-    }
-
-}

+ 0 - 78
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/SpringSecurityUser.java

@@ -1,78 +0,0 @@
-package cn.iocoder.yudao.framework.security.core.authentication;
-
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * 登录用户信息
- *
- * @author 芋道源码
- */
-@Data
-@AllArgsConstructor
-public class SpringSecurityUser implements UserDetails {
-
-    /**
-     * 用户编号
-     */
-    private Long id;
-
-    /**
-     * 用户名
-     */
-    private String username;
-    /**
-     * 密码
-     */
-    private String password;
-    /**
-     * 状态
-     */
-    private Integer status;
-    /**
-     * 租户编号
-     */
-    private Long tenantId;
-
-    @Override
-    public String getPassword() {
-        return password;
-    }
-
-    @Override
-    public String getUsername() {
-        return username;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return CommonStatusEnum.ENABLE.getStatus().equals(status);
-    }
-
-    @Override
-    public Collection<? extends GrantedAuthority> getAuthorities() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public boolean isAccountNonExpired() {
-        return true; // 返回 true,不依赖 Spring Security 判断
-    }
-
-    @Override
-    public boolean isAccountNonLocked() {
-        return true; // 返回 true,不依赖 Spring Security 判断
-    }
-
-    @Override
-    public boolean isCredentialsNonExpired() {
-        return true;  // 返回 true,不依赖 Spring Security 判断
-    }
-
-}

+ 1 - 4
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;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
@@ -29,8 +28,6 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
 
     private final SecurityProperties securityProperties;
 
-    private final MultiUserDetailsAuthenticationProvider authenticationProvider;
-
     private final GlobalExceptionHandler globalExceptionHandler;
 
     @Override
@@ -42,7 +39,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
             Integer userType = WebFrameworkUtils.getLoginUserType(request);
             try {
                 // 验证 token 有效性
-                LoginUser loginUser = authenticationProvider.verifyTokenAndRefresh(request, token);
+                LoginUser loginUser = null; // TODO 芋艿:待实现
                 // 模拟 Login 功能,方便日常开发调试
                 if (loginUser == null) {
                     loginUser = mockLoginUser(request, token, userType);

+ 0 - 1
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 {
     // ========== AUTH 模块 1004003000 ==========
     ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");
     ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1004003001, "登录失败,账号被禁用");
-    ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1004003002, "登录失败"); // 登录失败的兜底,未知原因
     ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期");
     ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定");
 

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http

@@ -1,5 +1,5 @@
 ### 请求 /login 接口 => 成功
-POST {{appApi}}/member/login
+POST {{appApi}}/member/auth/login
 Content-Type: application/json
 tenant-id: {{appTenentId}}
 

+ 0 - 7
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java

@@ -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 - 2
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java

@@ -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 {
 
     /**
      * 手机 + 密码登录

+ 25 - 61
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java

@@ -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);
+        }
+        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);
-        } 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();
+
+        // 构建 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;
+    }
+
 }

+ 9 - 0
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 {
      */
     void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO);
 
+    /**
+     * 判断密码是否匹配
+     *
+     * @param rawPassword 未加密的密码
+     * @param encodedPassword 加密后的密码
+     * @return 是否匹配
+     */
+    boolean isPasswordMatch(String rawPassword, String encodedPassword);
+
 }

+ 16 - 1
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 {
         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) {

+ 2 - 3
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;
 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

+ 0 - 3
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;
 
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.security.core.authentication.SpringSecurityUser;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
@@ -24,8 +23,6 @@ public interface AuthConvert {
 
     LoginUser convert(AdminUserDO bean);
 
-    SpringSecurityUser convert2(AdminUserDO user);
-
     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 - 1
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;
  *
  * @author 芋道源码
  */
-public interface AdminAuthService extends SecurityAuthFrameworkService {
+public interface AdminAuthService {
 
     /**
      * 账号登录

+ 3 - 15
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;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -226,11 +224,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         createLogoutLog(loginUser.getId());
     }
 
-    @Override
-    public UserTypeEnum getUserType() {
-        return UserTypeEnum.ADMIN;
-    }
-
     private void createLogoutLog(Long userId) {
         LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
         reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_SELF.getType());
@@ -244,11 +237,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         loginLogService.createLoginLog(reqDTO);
     }
 
-    @Override
-    public LoginUser verifyTokenAndRefresh(String token) {
-        return userSessionService.getLoginUser(token);
-    }
-
     private LoginUser buildLoginUser(AdminUserDO user) {
         return AuthConvert.INSTANCE.convert(user).setUserType(getUserType().getValue());
     }
@@ -261,8 +249,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         return user != null ? user.getUsername() : null;
     }
 
-    @Override
-    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-        return null;
+    private UserTypeEnum getUserType() {
+        return UserTypeEnum.ADMIN;
     }
+
 }