基本原理
Spring Security都使用了設計模式中的責任鏈模式,它們都定義了許多過濾器(Filter)澳化,每一個請求都會經(jīng)過層層過濾器的處理蒋纬。
其中,Spring Security 在 Servlet 的過濾鏈(filter chain)中注冊了一個過濾器 FilterChainProxy伊磺,它會把請求代理到 Spring Security 自己維護的多個過濾鏈,每個過濾鏈會匹配一些 URL删咱,如圖中的 /foo/**屑埋,如果匹配則執(zhí)行對應的過濾器。過濾鏈是有順序的痰滋,一個請求只會執(zhí)行第一條匹配的過濾鏈摘能。
Spring Security 的配置本質(zhì)上就是新增、刪除敲街、修改過濾器
為便于使用团搞,Spring Security默認實現(xiàn)了很多的過濾器,如 UsernamePasswordAuthenticationFilter
來處理用戶名密碼的認證多艇, SessionManagementFilter
來管理 Session 等等逻恐。
下面以 UsernamePasswordAuthenticationFilter
為例來講講Spring Security的認證過程。其實也簡單峻黍,就兩步:
-
UsernamePasswordAuthenticationFilter
攔截器匹配/login
的POST
請求复隆,保存認證信息(用戶名和密碼) - 最終由用戶實現(xiàn)
UsernamePasswordAuthenticationProvider
(authenticate
方法) 進行實際認證
代碼邏輯
代碼比較清晰,主要關注幾點:
- 由
UsernamePasswordAuthenticationFilter
定義了過濾器需要匹配的url -
UsernamePasswordAuthenticationFilter
的父類AbstractAuthenticationProcessingFilter
定義doFilter
方法實現(xiàn)整個認證流程姆涩,該過程調(diào)用attemtAuthentication
進行認證挽拂,保存認證結(jié)果并根據(jù)結(jié)果調(diào)用successfulAuthentication
或者unsuccessfulAuthentication
。 -
attemtAuthentication
方法最終會由用戶實現(xiàn)的UsernamePasswordAuthenticationProvider
(authenticate
方法) 進行實際認證
UsernamePasswordAuthenticationFilter定義過濾器需要匹配的url(/login
的POST
請求)
UsernamePasswordAuthenticationFilter
繼承AbstractAuthenticationProcessingFilter
用于處理/login
的POST
請求
AbstractAuthenticationProcessingFilter定義doFilter
方法實現(xiàn)整個認證流程
在AbstractAuthenticationProcessingFilter
的doFilter
方法中會調(diào)用attemptAuthentication
方法骨饿,該方法進行認證生成認證結(jié)果亏栈,最終認證結(jié)果由session處理。
UsernamePasswordAuthenticationProvider(authenticate
方法) 進行實際認證
UsernamePasswordAuthenticationFilter執(zhí)行認證
UsernamePasswordAuthenticationFilter
會實現(xiàn)父類中的attemptAuthentication
方法宏赘,該方法首先生成UsernamePasswordAuthenticationToken
保存認證信息绒北。然后調(diào)用AuthenticationManager
的authenticate
方法認證。
注意: 不同的filter會將認證信息保存到不同類型的結(jié)果中, 后續(xù)Spring Security會根據(jù)認證信息類型尋找合適的
AuthenticationProvider
進行認證置鼻,UsernamePasswordAuthenticationFilter
將結(jié)果保存到UsernamePasswordAuthenticationToken
中镇饮。
AuthenticationManager調(diào)用各AuthenticationProvider執(zhí)行認證
ProviderManager
實現(xiàn)AuthenticationManager
接口, ProviderManager
首先通過AuthenticationProvider
中的support
方法找到合適的AuthenticationProvider
,然后調(diào)用authenticate
認證方法
對于UsernamePasswordAuthenticationFilter
,通常我們需要實現(xiàn)自己的UsernamePasswordAuthenticationProvider
(實現(xiàn)AuthenticationProvider
接口)用于用戶名和密碼驗證以及加入一些需要的用戶信息如角色储藐、權(quán)限等到認證結(jié)果中俱济。
示例:
源碼
https://gitee.com/awesome-engineer/spring-cloud-family-bucket