国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - SpringBoot + SpringSecurity 短信驗證碼登錄功能實現

SpringBoot + SpringSecurity 短信驗證碼登錄功能實現

2021-05-09 12:27whyalwaysmea Java教程

這篇文章主要介紹了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

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 激情欧美一区二区三区中文字幕 | 中文字幕日韩在线视频 | 日韩在线精品强乱中文字幕 | 蜜臀网 | 国产精品视频网 | 成人av观看| 永久免费看黄色 | 国产美女精品人人做人人爽 | 国产精品美乳一区二区免费 | 免费在线看污网站 | 午夜精品一区二区三区在线视频 | 日韩三级在线 | 国产高清在线精品一区二区三区 | 日本一区二区三区四区 | 天天爽天天干 | 综合伊人久久 | 午夜影院在线 | 欧美亚洲自拍偷拍 | 欧美一级片在线观看 | 黄色在线观看网站 | 国产精品亲子伦av一区二区三区 | 久久小视频 | 久久香蕉网 | 99久久综合精品五月天 | 日本精品一区二区三区在线观看 | 毛片国产 | 懂色av成人一区二区三区 | 欧美福利在线观看 | 国产免费av在线 | 在线午夜电影 | 亚洲综合无码一区二区 | 国产精品美女av | 精品免费av | 日韩欧美一区二区三区 | 黄色一级片黄色一级片 | 一区二区三区日韩 | 亚洲成av人影片在线观看 | 欧美在线视频网站 | 伊人中文 | 日韩一区在线视频 | 欧美特级 |