• 若依 Spring Security 短信,扫码登录


    1.  修改  LoginBody,添加登录类型字段

    1. @Data
    2. public class LoginBody {
    3. /**
    4. * 用户名
    5. */
    6. private String username;
    7. /**
    8. * 用户密码
    9. */
    10. private String password;
    11. /**
    12. * 验证码
    13. */
    14. private String code;
    15. /**
    16. * 唯一标识
    17. */
    18. private String uuid;
    19. /**
    20. * 登录类型
    21. */
    22. private String loginType;
    23. }

    2.定义一个常量

    1. package com.ruoyi.common.core.domain.constant;
    2. /**
    3. * @author Ls
    4. * @date 2024/6/4
    5. */
    6. public class LoginTypeConstant {
    7. public static final String PASSWORD_LOGIN = "password";
    8. public static final String MOBILE_LOGIN = "mobile";
    9. public static final String QR_CODE_LOGIN = "qrCode";
    10. }

    3.修改登录接口

    1. @PostMapping("/login")
    2. public AjaxResult login(@RequestBody LoginBody loginBody) {
    3. AjaxResult ajax = AjaxResult.success();
    4. loginBody.setLoginType(LoginTypeConstant.MOBILE_LOGIN);
    5. // 生成令牌
    6. String token = loginService.login(loginBody);
    7. ajax.put(Constants.TOKEN, token);
    8. return ajax;
    9. }

    4.重载登录实现类,基本不用改,loginbody 作为 credentials传入UsernamePasswordAuthenticationToken 

    1. public String login(LoginBody loginBody) {
    2. String username = loginBody.getUsername();
    3. // // 验证码校验
    4. // validateCaptcha(username, code, uuid);
    5. // // 登录前置校验
    6. // loginPreCheck(username, password);
    7. // 用户验证
    8. Authentication authentication = null;
    9. try {
    10. UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, loginBody);
    11. AuthenticationContextHolder.setContext(authenticationToken);
    12. // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
    13. authentication = authenticationManager.authenticate(authenticationToken);
    14. } catch (Exception e) {
    15. if (e instanceof BadCredentialsException) {
    16. AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
    17. throw new UserPasswordNotMatchException();
    18. } else {
    19. AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
    20. throw new ServiceException(e.getMessage());
    21. }
    22. } finally {
    23. AuthenticationContextHolder.clearContext();
    24. }
    25. AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
    26. LoginUser loginUser = (LoginUser) authentication.getPrincipal();
    27. recordLoginInfo(loginUser.getUserId());
    28. // 生成token
    29. return tokenService.createToken(loginUser);
    30. }

    5.自定义MyAuthenticationProvider类

    1. package com.ruoyi.framework.security.mobile;
    2. import com.ruoyi.common.core.domain.constant.LoginTypeConstant;
    3. import com.ruoyi.common.core.domain.model.LoginBody;
    4. import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
    5. import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.security.authentication.AuthenticationProvider;
    8. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    9. import org.springframework.security.core.Authentication;
    10. import org.springframework.security.core.AuthenticationException;
    11. import org.springframework.security.core.userdetails.UserDetails;
    12. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    13. import org.springframework.stereotype.Component;
    14. /**
    15. * @author Ls
    16. * @date 2024/6/4
    17. */
    18. @Component
    19. public class MyAuthenticationProvider implements AuthenticationProvider {
    20. @Autowired
    21. private UserDetailsServiceImpl userDetailsService;
    22. @Autowired
    23. private BCryptPasswordEncoder bCryptPasswordEncoder;
    24. @Override
    25. public Authentication authenticate(Authentication authentication) throws AuthenticationException, UserPasswordNotMatchException {
    26. String name = authentication.getName();
    27. LoginBody loginBody = (LoginBody) authentication.getCredentials();
    28. String loginType = loginBody.getLoginType();
    29. UserDetails user;
    30. switch (loginType) {
    31. case LoginTypeConstant.PASSWORD_LOGIN:
    32. user = userDetailsService.loadUserByUsername(name);
    33. String password = loginBody.getPassword();
    34. String encoderPassword = bCryptPasswordEncoder.encode(password);
    35. // 数据库账号密码的校验能通过就通过
    36. if (bCryptPasswordEncoder.matches(password, user.getPassword())) {
    37. return new UsernamePasswordAuthenticationToken(user, encoderPassword);
    38. }
    39. case LoginTypeConstant.MOBILE_LOGIN:
    40. user = userDetailsService.loadUserByPhone(loginBody);
    41. return new UsernamePasswordAuthenticationToken(user, loginBody.getCode());
    42. case LoginTypeConstant.QR_CODE_LOGIN:
    43. break;
    44. default:
    45. break;
    46. }
    47. // 如果都登录不了,就返回异常输出
    48. throw new UserPasswordNotMatchException();
    49. }
    50. @Override
    51. public boolean supports(Class aClass) {
    52. return true;
    53. }
    54. }

    6.用户验证类新增手机号登录 UserDetailsServiceImpl 

    1. public UserDetails loadUserByPhone(LoginBody loginBody) throws UsernameNotFoundException {
    2. // TODO: 2024/6/4 各种业务效验,这里图省事验证码放在password
    3. if (!Objects.equals(loginBody.getPassword(), "123456")) {
    4. throw new ServiceException("验证码错误");
    5. }
    6. //这里应该是根据手机号查询,我这里图省事直接拿账号登录
    7. String username = loginBody.getUsername();
    8. SysUser user = userService.selectUserByUserName(username);
    9. return createLoginUser(user);
    10. }

    7.SecurityConfig调整,配置一下MyAuthenticationProvider

    1. /**
    2. * 自定义用户认证逻辑
    3. */
    4. @Autowired
    5. private MyAuthenticationProvider myAuthenticationProvider;
    6. /**
    7. * 身份认证接口
    8. */
    9. @Override
    10. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    11. auth.authenticationProvider(myAuthenticationProvider);
    12. }
    
                    
  • 相关阅读:
    Paparazzi: Surface Editing by way of Multi-View Image Processing
    Git的入门详细教程
    云原生Kubernetes: 云主机部署K8S 1.30版本 单Master架构
    HTML是指什么 HTML的基本工作原理
    Redis哨兵模式详解
    CiscoCUCM路由
    Github学生认证
    高频CSS面试题
    [题]Balanced Lineup G #倍增
    一步一步教你构建springboot
  • 原文地址:https://blog.csdn.net/qq_39845279/article/details/139447796