1. 程式人生 > >Spring Security登入驗證流程原始碼解析

Spring Security登入驗證流程原始碼解析

一、登入認證基於過濾器鏈

Spring Security的登入驗證流程核心就是過濾器鏈。當一個請求到達時按照過濾器鏈的順序依次進行處理,通過所有過濾器鏈的驗證,就可以訪問API介面了。

SpringSecurity提供了多種登入認證的方式,由多種Filter過濾器來實現,比如:

  • BasicAuthenticationFilter實現的是HttpBasic模式的登入認證
  • UsernamePasswordAuthenticationFilter實現使用者名稱密碼的登入認證
  • RememberMeAuthenticationFilter實現登入認證的“記住我”的功能
  • SmsCodeAuthenticationFilter實現簡訊驗證碼登入認證
  • SocialAuthenticationFilter實現社交媒體方式登入認證的處理
  • Oauth2AuthenticationProcessingFilter和Oauth2ClientAuthenticationProcessingFilter實現Oauth2的鑑權方式

根據我們不同的需求實現及配置,不同的Filter會被載入到應用中。

二、結合原始碼講解登入驗證流程

我們就以使用者名稱、密碼登入方式為例講解一下Spring Security的登入認證流程。

2.1 UsernamePasswordAuthenticationFilter

該過濾器封裝使用者基本資訊(使用者名稱、密碼),定義登入表單資料接收相關的資訊。如:

  • 預設的表單使用者名稱密碼input框name是username、password
  • 預設的處理登入請求路徑是/login、使用POST方法


2.2 AbstractAuthenticationProcessingFilter的doFilter方法的驗證過程

UsernamePasswordAuthenticationFilter繼承自抽象類AbstractAuthenticationProcessingFilter,該抽象類定義了驗證成功與驗證失敗的處理方法。

2.3 驗證成功之後的Handler和驗證失敗之後的handler

也就是說當我們需要自定義驗證成功或失敗的處理方法時,要去實現AuthenticationSuccessHandler或AuthenticationfailureHandler介面

三、登入驗證內部細節

3.1多種認證方式的管理 ProviderManager

ProviderManager用繼承於AuthenticationManager是登入驗證的核心類。ProviderManager保管了多個AuthenticationProvider,用於不同型別的登入驗證。比如:

  • RememberMeAuthenticationProvider定義了“記住我”功能的登入驗證邏輯
  • DaoAuthenticationProvider載入資料庫使用者資訊,進行使用者密碼的登入驗證
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
    ……
    private List<AuthenticationProvider> providers;
    ……

下文是ProviderManager的核心原始碼,遍歷不同登入驗證的AuthenticationProvider,只有當這種方式被支援的時候,才執行具體的登入驗證邏輯。

3.2 登入認證介面 AuthenticationProvider

public interface AuthenticationProvider {
    Authentication authenticate(Authentication var1) throws AuthenticationException;

    boolean supports(Class<?> var1);
}

AuthenticationProvider的實現類定義了具體的登入驗證邏輯

3.3 資料庫載入使用者資訊 DaoAuthenticationProvider

public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

從資料庫獲取使用者資訊原始碼

所以當我們需要載入使用者資訊進行登入驗證的時候,我們需要實現UserDetailsService介面,重寫loadUserByUsername方法,引數是使用者輸入的使用者名稱。返回值是UserDetails

期待您的關注

  • 博主最近新寫了一本書:《手摸手教您學習SpringBoot系列-16章97節》
  • 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格。