Spring Security 框架結構知識(持續更新)

概述

Spring Security 是一款安全管理框架,在SpringBoot/SpringCloud環境下可以達成0配置的方式集成,非常方便

大致模型

在這裏插入圖片描述

DelegatingFilterProxy

Spring提供了一個名爲DelegatingFilterProxy的過濾器實現,它允許在Servlet容器的生命週期和Spring的ApplicationContext之間架橋

FilterChainProxy

這是Spring Security提供的過濾器鏈代理,它被包含在DelegatingFilterProxy過濾器中,在接受請求時會經由FilterChainProxy決定來使用哪一條SecurityFilterChain過濾器鏈

SecurityFilterChain

這個是由FilterChainProxy代理來決定實例的調用,這樣對每一套匹配我們都可以有細緻的配置,其中SecurityFilterChain實例下的SecurityFilter一般都是Bean

在過濾器鏈代理對象中可以有一個或多個過濾器鏈,在多個過濾器鏈中一個請求會匹配首個滿足匹配條件的過濾器鏈

默認Chain下的Filter

  • ChannelProcessingFilter:確保web請求通過通道的過濾器
  • ConcurrentSessionFilter:併發會話處理包所需的過濾器,這個過濾器會進行兩個操作,一是爲每個請求設置最後一次請求事件,二是檢索回話信息檢查回話是否被標識爲已過時,如果過時則會使其失效
  • WebAsyncManagerIntegrationFilter:填充SecurityContext的過濾器
  • SecurityContextPersistenceFilter:請求處理前從SecurityContextRepository獲取SecurityContext並在請求結束後清除此SecurityContext
  • HeaderWriterFilter:爲請求添加一些頭部信息的過濾器
  • CsrfFilter:使用同步器令牌模式應用CSRF保護,開發人員需要確保對任何允許狀態更改的請求調用CsrfFilter
  • LogoutFilter:用戶退出的過濾器,他會順序的調用LogoutSuccessHandlerLogoutHandler
  • OAuth2AuthorizationRequestRedirectFilter:此過濾器通過將最終用戶的用戶代理重定向到授權服務器的授權端點來啓動授權代碼授予
  • Saml2WebSsoAuthenticationRequestFilter:不知道是什麼用
  • X509AuthenticationFilter:支持X509身份驗證的過濾器
  • AbstractPreAuthenticatedProcessingFilter:預處理過濾器,對身份驗證的預先處理,默認情況下如果認證失敗任然會繼續下一個過濾器
  • CasAuthenticationFilter:不知道
  • OAuth2LoginAuthenticationFilter:用於OAuth 2.0登錄的過濾器實現
  • Saml2WebSsoAuthenticationFilter:不知道
  • UsernamePasswordAuthenticationFilter:處理表單提交的身份驗證,默認需要兩個參數(username和password)進行身份驗證,這個過濾器默認響應於請求/loginURL的請求
  • OpenIDAuthenticationFilter:處理OpenID身份驗證請求的過濾器
  • DefaultLoginPageGeneratingFilter:在用戶沒有配置登錄頁面時將會插入到過濾器鏈的過濾器,提供了默認登錄頁面配置等等
  • DefaultLogoutPageGeneratingFilter:構建一個默認的退出登錄頁面配置的過濾器
  • DigestAuthenticationFilter:處理摘要身份驗證的處理器
  • BearerTokenAuthenticationFilter:認證包含OAuth 2.0承載令牌的請求,此過濾器應該被寫入AuthenticationManagerBearerTokenAuthenticationToken能被AuthenticationManager驗證
  • BasicAuthenticationFilter:基於Basic的身份驗證過濾器
  • RequestCacheAwareFilter:如果緩存了一個與當前請求匹配的請求對象,負責重新構造所緩存的請求,它將會調用配置的RequestCache上的getMatchingRequest (),如果方法返回一個增強的request則會將它交給doFilter(),如果方法返回null將使用原始的請求,過濾器是沒有效果的
  • SecurityContextHolderAwareRequestFilter:對請求對象進行包裝增強的過濾器,這個過濾器爲請求擴展了以下幾個方法
    • HttpServletRequest.authenticate(HttpServletResponse):允許用戶確定他們是否經過身份驗證,如果沒有則將用戶發送到登錄頁面
    • HttpServletRequest.login(String, String):允許用戶通過AuthenticationManager進行身份驗證
    • HttpServletRequest.logout():允許使用配置的LogoutHandler進行註銷
    • AsyncContext.start(Runnable):自動的複製從當前線程的SecurityContextHolder找到的SecurityContextRunable線程
  • JaasApiIntegrationFilter:試圖獲取JAAS Subject並繼續作爲該Subject運行的過濾器
  • RememberMeAuthenticationFilter:檢測SecurityContext中是否沒有Authentication對象,如果RememberMeServices有被實現,則將Authentication填充到SecurityContext中,通過過濾器調用RememberMeServicesautoLogin()方法,如果該方法返回一個非空Authentication對象則會把此對象傳遞給AuthenticationManager
  • AnonymousAuthenticationFilter:檢測SecurityContext中是否沒有Authentication對象,並在需要時填充一個,默認實現是在沒有Authentication對象時創建一個匿名的Authentication對象放入到SecurityContext
  • OAuth2AuthorizationCodeGrantFilter:OAuth 2.0授權代碼授予的過濾器,它處理OAuth 2.0授權響應的處理
  • SessionManagementFilter:檢測用戶自請求開始以來已經通過身份驗證,如果已經通過,則調用配置的SessionAuthenticationStrategy來執行任何與會話相關的活動
  • ExceptionTranslationFilter:處理在過濾器鏈中拋出的任何AccessDeniedExceptionAuthenticationException異常
  • FilterSecurityInterceptor:通過過濾器實現執行HTTP資源的安全處理
  • SwitchUserFilter:切換用戶處理過濾器負責用戶上下文切換

Security Filters

這個是過濾器鏈中的具體過濾器,經由SecurityFilterChain來進行註冊



Authentication 認證

Spring Security 提供了全面的身份驗證功能

以下是基於servlet應用會用到的一些組件

  • SecurityContextHolder:SecurityContextHolder是Spring Security身份驗證的地方
  • SecurityContext:是從SecurityContextHolder獲取且包含當前已認證用戶的Authentication對象信息的組件
  • Authentication:可以被輸入到AuthenticationManager中去提供給認證一個用戶或則認證當前用戶
  • GrantedAuthority:在認證過程中授予主體(用戶)的權限組件
  • AuthenticationManager:定義Spring Security的過濾器如何執行身份驗證的API
  • ProviderManager:AuthenticationManager最常見的實現
  • AuthenticationProvider:由ProviderManager用於執行特定類型的身份驗證
  • Request Credentials with AuthenticationEntryPoint:用於從客戶端請求憑據
  • AbstractAuthenticationProcessingFilter:用於身份驗證的基本過濾器

SecurityContextHolder

SecurityContextHolderSecurityContext的獲取器,他可以獲取、創建SecurityContext

默認的情況下SecurityContextHolder是使用一個ThreadLocal來儲存這些細節,這就意味着SecurityContextHolder只會在同一線程下的方法中可用,但我們也可以通過設置來改變這個默認模式

SecurityContext

這個SecurityContext是從SecurityContextHolder獲取得到的,SecurityContext包含着Authentication認證信息對象

Authentication

這個Authentication主要用於以下兩個用途

  1. 作爲AuthenticationManager的輸入,提供用戶所提供的身份驗證的憑證,此時用戶是未認證的,自然isAuthenticated()false
  2. 代表當前已經認證的用戶,當前這個Authentication是可以通過SecurityContext獲取得到

這個Authentication主要包含了

  • principal:識別用戶,當使用用戶名/密碼進行身份驗證時,這通常是UserDetails的一個實例
  • credentials:通常代表一個密碼,在用戶通過認證且保證不泄露的情況下通常會被清除掉
  • authorities:賦予用戶的權限

GrantedAuthority

GrantedAuthority是給用戶賦予的權限,例如角色、範圍等

GrantedAuthority可以從Authentication.getAuthorities()方法中獲得

AuthenticationManager

AuthenticationManager是定義Spring Security的過濾器如何執行身份驗證的API

ProviderManager

ProviderManager是最常用的AuthenticationManager實現方式,ProviderManager代表一個AuthenticationProvider的集合,其中每一個AuthenticationProvider都有機會去決定身份驗證是否成功、失敗、或則不下決定而交給下游的AuthenticationProvider做決定,如果配置的AuthenticationProvider都不能夠作出決定那麼將會拋出AuthenticationException異常,代表不能處理這種身份驗證
在這裏插入圖片描述

AuthenticationProvider的集合中,每一個AuthenticationProvider都可以處理不同類型的身份驗證,例如第一個處理的是用戶名/密碼,第二個處理的是SAML,他們互不影響
在這裏插入圖片描述

我們可以爲ProviderManager配置一個父AuthenticationManager,在自身沒有可處理的AuthenticationProvider時候,將會去請求這個父AuthenticationProvider管理器,通常這個是一個ProviderManager實例

默認情況下,ProviderManager將嘗試從成功的身份驗證請求返回的`Authentication`對象中清除任何敏感的憑據(密碼)信息,因此會產生一些問題,如果在之後想獲取已認證的用戶憑證是沒有的,對此有兩個解決方案
  • 對返回的Authentication進行拷貝加入緩存,保留用戶憑着
  • 禁用ProviderManagereraseCredentialsAfterAuthentication屬性,保留憑着

AuthenticationProvider

我們可以將多個AuthenticationProvider注入到ProviderManager中,每一個AuthenticationProvider都執行特定類型的認證

AuthenticationEntryPoint

AuthenticationEntryPoint用於發送從客戶端請求憑據的HTTP響應

AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter是用於驗證用戶憑證的基本Filter,在認證憑證之前,Spring Security通常使用AuthenticationEntryPoint請求憑證
在這裏插入圖片描述

大體的執行流程

  1. 當用戶提交憑證,這個AbstractAuthenticationProcessingFilter將通過HttpServletRequest創建一個Authentication對象用於身份驗證,這個Authentication的類型依賴於AbstractAuthenticationProcessingFilter的子類
  2. Authentication傳遞給AuthenticationManager進行身份驗證
  3. 如果驗證失敗
    • 這個SecurityContextHolder會被清除
    • RememberMeServices.loginFail將會被調用,如果有配置的話
    • AuthenticationFailureHandler被調用
  4. 如果驗證成功
    • SessionAuthenticationStrategy收到新登錄的通知
    • 這個Authentication設置在SecurityContextHolder中,隨後,SecurityContextPersistenceFilterSecurityContext保存到HttpSession
    • RememberMeServices.loginSuccess將被調用,如果有配置的話
    • ApplicationEventPublisher觸發一個InteractiveAuthenticationSuccessEvent事件




用戶名/密碼認證

用戶名/密碼是最爲常見的身份驗證方式,Spring Security爲此提供和非常廣泛的支持

Spring Security提供了以下內置機制,用於從HttpServletRequest讀取用戶名和密碼

表單登錄

Spring Security可以通過表單中的內容獲取登錄所需的用戶名密碼,在沒有任何配置的情況下是默認打開的,但是如果有任何servlet配置的情況下需要手動指定

protected void configure(HttpSecurity http) {
    // 配置
    http.formLogin(withDefaults());
}
對於默認HTML表單提交配置我們需要注意幾點:
1.表單應該以post提交方式進行認證
2.表單應該指明username參數爲用戶名
2.表單應該指明password參數爲密碼

Authorization 授權

權限對象由一個GrantedAuthority接口表示,權限對象由AuthenticationManager插入到Authentication對象中,然後由AccessDecisionManager s在進行授權決策時讀取

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章