gpt4 book ai didi

SpringBoot + SpringSecurity 短信验证码登录功能实现

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 28 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章SpringBoot + SpringSecurity 短信验证码登录功能实现由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

实现原理 。

在之前的文章中,我们介绍了普通的帐号密码登录的方式: SpringBoot + Spring Security 基本使用及个性化登录配置。 但是现在还有一种常见的方式,就是直接通过手机短信验证码登录,这里就需要自己来做一些额外的工作了.

对SpringSecurity认证流程详解有一定了解的都知道,在帐号密码认证的过程中,涉及到了以下几个类:UsernamePasswordAuthenticationFilter(用于请求参数获取),UsernamePasswordAuthenticationToken(表示用户登录信息),ProviderManager(进行认证校验), 。

因为是通过的短信验证码登录,所以我们需要对请求的参数,认证过程,用户登录Token信息进行一定的重写。 当然验证码的过程我们应该放在最前面,如果图形验证码的实现一样。这样的做法的好处是:将验证码认证该过程解耦出来,让其他接口也可以使用到.

基本实现 。

验证码校验 。

短信验证码的功能实现,其实和图形验证码的原理是一样的。只不过一个是返回给前端一个图片,一个是给用户发送短消息,这里只需要去调用一下短信服务商的接口就好了。更多的原理可以参考 SpringBoot + SpringSecurity 实现图形验证码功能 。

AuthenticationToken 。

在使用帐号密码登录的时候,UsernamePasswordAuthenticationToken里面包含了用户的帐号,密码,以及其他的是否可用等状态信息。我们是通过手机短信来做登录,所以就没有密码了,这里我们就直接将UsernamePasswordAuthenticationToken的代码copy过来,把密码相关的信息去掉就可以了 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken {
 
   private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
 
   private final Object principal;
 
   public SmsCodeAuthenticationToken(String mobile) {
     super ( null );
     this .principal = mobile;
     setAuthenticated( false );
   }
 
   public SmsCodeAuthenticationToken(Object principal,
                    Collection<? extends GrantedAuthority> authorities) {
     super (authorities);
     this .principal = principal;
     super .setAuthenticated( true ); // must use super, as we override
   }
 
   public Object getCredentials() {
     return null ;
   }
 
   public Object getPrincipal() {
     return this .principal;
   }
 
   public void setAuthenticated( boolean isAuthenticated) throws IllegalArgumentException {
     if (isAuthenticated) {
       throw new IllegalArgumentException(
           "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead" );
     }
     super .setAuthenticated( false );
   }
 
   @Override
   public void eraseCredentials() {
     super .eraseCredentials();
   }
}

AuthenticationFilter 。

在帐户密码登录的流程中,默认使用的是UsernamePasswordAuthenticationFilter,它的作用是从请求中获取帐户、密码,请求方式校验,生成AuthenticationToken。这里我们的参数是有一定改变的,所以还是老方法,copy过来进行简单的修改 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
   // 请求参数key
   private String mobileParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_MOBILE;
   // 是否只支持POST
   private boolean postOnly = true ;
 
   public SmsCodeAuthenticationFilter() {
     // 请求接口的url
     super ( new AntPathRequestMatcher(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE, "POST" ));
   }
 
   public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
       throws AuthenticationException {
     if (postOnly && !request.getMethod().equals( "POST" )) {
       throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod());
     }
     // 根据请求参数名,获取请求value
     String mobile = obtainMobile(request);
     if (mobile == null ) {
       mobile = "" ;
     }
     mobile = mobile.trim();
 
     // 生成对应的AuthenticationToken
     SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(mobile);
 
     setDetails(request, authRequest);
 
     return this .getAuthenticationManager().authenticate(authRequest);
   }
 
   /**
    * 获取手机号
    */
   protected String obtainMobile(HttpServletRequest request) {
     return request.getParameter(mobileParameter);
   }
   // 省略不相关代码
}

Provider 。

在帐号密码登录的过程中,密码的正确性以及帐号是否可用是通过DaoAuthenticationProvider来校验的。我们也应该自己实现一个Provier 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {
 
   private UserDetailsService userDetailsService;
 
   /**
    * 身份逻辑验证
    * @param authentication
    * @return
    * @throws AuthenticationException
    */
   @Override
   public Authentication authenticate(Authentication authentication) throws AuthenticationException {
 
     SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication;
 
     UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());
 
     if (user == null ) {
       throw new InternalAuthenticationServiceException( "无法获取用户信息" );
     }
 
     SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user, user.getAuthorities());
 
     authenticationResult.setDetails(authenticationToken.getDetails());
 
     return authenticationResult;
   }
 
   @Override
   public boolean supports(Class<?> authentication) {
     return SmsCodeAuthenticationToken. class .isAssignableFrom(authentication);
   }
 
   public UserDetailsService getUserDetailsService() {
     return userDetailsService;
   }
 
   public void setUserDetailsService(UserDetailsService userDetailsService) {
     this .userDetailsService = userDetailsService;
   }
}

配置 。

主要的认证流程就是通过以上四个过程实现的, 这里我们再降它们配置一下就可以了 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Component
public class SmsCodeAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
 
   @Autowired
   private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
 
   @Autowired
   private AuthenticationFailureHandler myAuthenticationFailureHandler;
 
   @Autowired
   private UserDetailsService userDetailsService;
 
   @Override
   public void configure(HttpSecurity http) throws Exception {
 
     SmsCodeAuthenticationFilter smsCodeAuthenticationFilter = new SmsCodeAuthenticationFilter();
     smsCodeAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager. class ));
     smsCodeAuthenticationFilter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
     smsCodeAuthenticationFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
 
     SmsCodeAuthenticationProvider smsCodeAuthenticationProvider = new SmsCodeAuthenticationProvider();
     smsCodeAuthenticationProvider.setUserDetailsService(userDetailsService);
 
     http.authenticationProvider(smsCodeAuthenticationProvider)
         .addFilterAfter(smsCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter. class );
 
   }
}
 
// BrowerSecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
   http.apply(smsCodeAuthenticationSecurityConfig);
}

代码下载 。

Spring-Security 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:https://blog.csdn.net/u013435893/article/details/79684027 。

最后此篇关于SpringBoot + SpringSecurity 短信验证码登录功能实现的文章就讲到这里了,如果你想了解更多关于SpringBoot + SpringSecurity 短信验证码登录功能实现的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com