1. 認(rèn)證組件列表
-
SecurityContextHolder
存儲(chǔ)認(rèn)證過的用戶的詳細(xì)信息 -
SecurityContext
包含在SecurityContextHolder
中, 存儲(chǔ)當(dāng)前已認(rèn)證用戶的信息(Authentication
對(duì)象) -
Authentication
提供給AuthenticationManager
以提供用戶憑證(密碼), 或者當(dāng)前用戶 -
GrantedAuthority
授予用戶的權(quán)限. -
AuthenticationManager
決定調(diào)用哪個(gè)身份認(rèn)證過濾器 -
ProviderManager
AuthenticationManager
最常用的實(shí)現(xiàn). -
AuthenticationEntryPoint
用來向客戶端請(qǐng)求憑證(如重定向到登錄頁面, 或返回一個(gè)www-authenticate響應(yīng)) -
AbstractAuthenticationProcessingFilter
用于進(jìn)行認(rèn)證的基本Filter.
2. SecutiryContextHolder
SecutiryContextHolder
用于存儲(chǔ)已認(rèn)證用戶的信息, 它不關(guān)心用戶是如何通過認(rèn)證的, 只要包含一個(gè)值, 則這個(gè)值將被用來作為一個(gè)已認(rèn)證用戶. 這是一個(gè)jvm設(shè)置, 因此其所有方法都是靜態(tài)的.
通過配置指定相關(guān)策略. 其實(shí)現(xiàn)被委托給 SecurityContextHolderStrategy
. 策略指定有兩種方法, 一種是系統(tǒng)屬性, 一種是調(diào)用靜態(tài)方法.
其策略有三種:
- ThreadLocal:
默認(rèn), 使用一個(gè)ThreadLocal來存儲(chǔ)用戶信息, 因此在同一個(gè)線程中可以獲取到用戶信息. - InheritableThreadLocal:
使用一個(gè)InheritableThreadLocal存儲(chǔ)用戶信息, 可以當(dāng)前線程創(chuàng)建的子線程中也可以獲取到用戶信息. - Global:
全局共享一個(gè)SecurityContext
.
獲取用戶信息:
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
String username = authentication.getName();
Object principal = authentication.getPrincipal();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
類圖:
3. SecurityContext
存儲(chǔ)Authentication對(duì)象.
4. Authentication
在成功調(diào)用AuthenticationManager.authenticate(Authentication)
方法后, 用于存儲(chǔ)已認(rèn)證用戶的信息.
如果其authenticated
屬性值為false, Spring Security都將會(huì)對(duì)其進(jìn)行驗(yàn)證.
Collection<? extends GrantedAuthority> getAuthorities()
用于獲取授予認(rèn)證主體的權(quán)限, 當(dāng)沒有權(quán)限時(shí)應(yīng)返回空集合,而不是null.
Object getDetails()
方法用于存儲(chǔ)認(rèn)證請(qǐng)求信息, 如IP地址, 憑證序列號(hào)等.
Object getPrincipal()
: 在使用用戶名和密碼登錄驗(yàn)證的請(qǐng)求中, 在認(rèn)證成功之前, 這通常是用戶名, 認(rèn)證成功后, 這通常是一個(gè)UserDetails對(duì)象.
boolean isAuthenticated()
: 用于指示AbstractSecurityInterceptor
是否將當(dāng)前的Authentication對(duì)象傳遞給AuthenticationManager
進(jìn)行身份驗(yàn)證.
5. GrantedAuthority
用于表示用戶所獲取的權(quán)限, 如角色. 如果使用用戶名密碼認(rèn)證, 權(quán)限應(yīng)由UserDetailsService
加載.
它用字符串來表示, 以便能進(jìn)行精確匹配.
6. AuthenticationManager
用于處理認(rèn)證請(qǐng)求. 認(rèn)證后會(huì)將用戶信息存儲(chǔ)到SecurityContext中. 其最常用的實(shí)現(xiàn)為ProviderManager
.
必須對(duì)以下異常進(jìn)行驗(yàn)證:
- 如果用戶被禁用,則應(yīng)拋出
DisabledException
. - 如果用戶被鎖定, 則應(yīng)拋出
LockedException
. - 如果憑證錯(cuò)誤, 則必須拋出badcredentialexception。
Authentication authenticate(Authentication authentication) throws AuthenticationException
: 如果調(diào)用成功則返回一個(gè)完全填充(包含了較全面的用戶信息)的Authentication對(duì)象.
7. ProviderManager
最常用的AuthenticationManager
實(shí)現(xiàn). 它包含一個(gè)AuthenticationProvider
集合. 每個(gè)provider對(duì)應(yīng)一種身份驗(yàn)證方式, 因此通過AuthenticationManager
可以支持多種身份驗(yàn)證方式. 如果請(qǐng)求沒有相應(yīng)的provider, 則將拋出ProviderNotFoundException
.
ProviderManager遍歷每個(gè)provider, 如果有一個(gè)provider返回非null結(jié)果, 則將不再調(diào)用后續(xù)未調(diào)用的provider.
此外, ProviderManager還可以配置一個(gè)parent, 當(dāng)ProviderManager無法進(jìn)行認(rèn)證時(shí), 可以調(diào)用這個(gè)parent. 這樣可以在有多個(gè)ProviderManager實(shí)例時(shí), 通過parent來處理公共認(rèn)證方式. parent可以是任何AuthenticationManager
實(shí)例, 但通常為ProviderManager
.
ProviderManager還負(fù)責(zé)在認(rèn)證成功后清除用戶憑證(密碼). 其eraseCredentialsAfterAuthentication
屬性值默認(rèn)為true. 這對(duì)于通過緩存用戶信息再進(jìn)行認(rèn)證的場景可能有影響(因?yàn)槊艽a被清除了). 解決方式是設(shè)置eraseCredentialsAfterAuthentication
為false.
認(rèn)證事件
可通過AuthenticationEventPublisher
來發(fā)布認(rèn)證事件(成功,失敗). 默認(rèn)是一個(gè)Null實(shí)現(xiàn)(不發(fā)布事件). 因此如果需要發(fā)布事件,則需要注入對(duì)應(yīng)的bean(DefaultAuthenticationEventPublisher
). ProviderManager的parent通常不需要配置publisher, 因?yàn)閙anager可以對(duì)parent的認(rèn)證結(jié)果發(fā)布相應(yīng)的事件, 從而造成事件 的重復(fù)發(fā)布.
AuthenticationManager類圖:
7. AuthenticationProvider
定義認(rèn)證方式.
8. AuthenticationEntryPoint
在ExceptionTranslationFilter
中用來定義認(rèn)證方案. 即返回給客戶端響應(yīng)以要求客戶端提供何種方式的認(rèn)證.
類圖:
9. AbstractAuthenticationProcessingFilter
身份驗(yàn)證的一個(gè)基礎(chǔ)Filter.
- 用戶提交認(rèn)證請(qǐng)求后, 它將從請(qǐng)求中獲取相關(guān)參數(shù)并創(chuàng)建一個(gè)
Authentication
對(duì)象(對(duì)象類型取決于其實(shí)現(xiàn)類). - Authentication對(duì)象被傳遞給
AuthenticationManager
進(jìn)行驗(yàn)證處理. - 如果驗(yàn)證不通過, 將清除
SecurityContextHolder
; 調(diào)用RememberMeService.loginFail
(如果配置了remeberme); 調(diào)用AuthenticationFailureHandler
. 如果驗(yàn)證通過, 通知SessionAuthenticationStrategy
有一個(gè)新的登錄; 存儲(chǔ)Authentication
到SecurityContextHolder
,SecurityContextPersistenceFilter
保存這個(gè)SecurityContext
到HttpSession
; 如果配置了remeberme, 調(diào)用RemeberMeService.loginSuccess
;ApplicationEventPublisher
發(fā)布一個(gè)InteractiveAuthenticationSuccessEvent
, 調(diào)用AuthenticationSuccessHandler
.
類圖: