spring security 認(rèn)證流程:

1. 當(dāng)?shù)卿洉r(shí),請(qǐng)求會(huì)被UsernamePasswordAuthenticationFilter 攔截, 獲取用戶(hù)名和密碼,封裝成UsernamePasswordAuthenticationToken,并交給AuthenticationManager(認(rèn)證核心接口)去認(rèn)證;
2. ProviderManager 是AuthenticationManager接口的實(shí)現(xiàn)類(lèi),也就是驗(yàn)證UsernamePasswordAuthenticationToken時(shí)交給它來(lái)處理。
3. ProviderManager 的authenticate(authentication) 方法,是驗(yàn)證UsernamePasswordAuthenticationToken的核心方法;從源碼可以得知:ProviderManager? 有 一個(gè)屬性為:List providers; 從名稱(chēng)就可以看出,是一個(gè)認(rèn)證器的集合;所以authenticate(authentication)方法的主要邏輯就是遍歷providers, support(UsernamePasswordAuthenticationToken)的AuthenticationProvider 會(huì)去做相應(yīng)的認(rèn)證;
AuthenticationProvider 認(rèn)證用戶(hù)三步走原則:
(1)獲取用戶(hù)信息
(2)檢查用戶(hù)“是否被禁用”,“是否被鎖定”,“是否過(guò)期”
(3)校驗(yàn)用戶(hù)名和密碼
4. 通過(guò)驗(yàn)證返回Authentication
5. 通過(guò)驗(yàn)證返回Authentication
6. 通過(guò)驗(yàn)證返回Authentication到 AbstractAuthenticationProcessingFilter
7. successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) 發(fā)布登錄成功;
主要邏輯為:
(1)Authentication保存到SecurityContext中; 源碼:SecurityContextHolder.getContext().setAuthentication(authResult);
(2)如果配合記住密碼,則會(huì)記住密碼;??? 源碼:this.rememberMeServices.loginSuccess(request, response, authResult);
?(3)? 請(qǐng)求之前未登錄狀態(tài)下請(qǐng)求的網(wǎng)址;??? 源碼:this.successHandler.onAuthenticationSuccess(request, response, authResult)
說(shuō)明:SecurityContextHolder.getContext().setAuthentication(authResult),底層源碼是使用new ThreadLocal() 存儲(chǔ)的,如果不了解?ThreadLocal,請(qǐng)自行查閱;
spring security 權(quán)限校驗(yàn)流程:

1. 第一次請(qǐng)求http://localhost:8088/persons方法時(shí),UsernamePasswordAuthenticationFilter? 不會(huì)攔截,因?yàn)閁sernamePasswordAuthenticationFilter? 只會(huì)攔截/login 且為POST,? 但是會(huì)被AnonymousAuthenticationFilter攔截,主要做的就是SecurityContextHolder.getContext().setAuthentication(AnonymousAuthenticationToken),具體請(qǐng)看源碼;然后會(huì)進(jìn)入到FilterSecurityInterceptor過(guò)濾器;FilterSecurityInterceptor 過(guò)濾器才是真正控制訪(fǎng)問(wèn)權(quán)限的Filter;
2. super.beforeInvocation(fi) 主要邏輯:
1)Authentication authenticated =this.authenticateIfRequired();?? 獲取token,從SecurityContextHolder.getContext()? 獲得
2)this.accessDecisionManager.decide(authenticated, object,attributes); ******這個(gè)才是重中之重*****作用就是判斷是否有訪(fǎng)問(wèn)權(quán)限;
?3. this.accessDecisionManager.decide(authenticated, object,attributes);會(huì)拋出AccessDeniedException |AuthenticationException異常,并被ExceptionTranslationFilter攔截,
如果為AccessDeniedException ,跳轉(zhuǎn)到未授權(quán)頁(yè)面
如果為AuthenticationException,跳轉(zhuǎn)登錄頁(yè)面
4. 由于未登錄跳轉(zhuǎn)到登錄頁(yè)
5. 填寫(xiě)用戶(hù)名和密碼再次請(qǐng)求,會(huì)走上面的認(rèn)證流程;? 認(rèn)證流程走完,最終還是會(huì)走到FilterSecurityInterceptor? 攔截器;然后還是會(huì)從? 2) 流程開(kāi)始走,不同的是這回已經(jīng)登錄,所以Authentication authenticated =this.authenticateIfRequired();獲取到的是包含用戶(hù)數(shù)據(jù),以及權(quán)限的信息;然后還是會(huì)走this.accessDecisionManager.decide(authenticated, object,attributes); 不拋出異常則到 第6步驟, 否則還是會(huì)從3 步驟開(kāi)始
?6. 訪(fǎng)問(wèn)到/persons 接口,進(jìn)入到Controller 中;
以上流程圖源自:
http://www.spring4all.com/article/439
http://www.spring4all.com/article/458
關(guān)鍵的類(lèi)和接口介紹:
AbstractAuthenticationProcessingFilter 類(lèi):在不同maven包下的展現(xiàn)形式:
spring-boot-starter-security包下:

spring-security-oauth2包下:


可以看出多了一個(gè)OAuth2ClientAuthenticationProcessingFilter和ClientCredentialsTokenEndpointFilter;
當(dāng)使用Oauth2認(rèn)證時(shí),主要走的兩個(gè)Filter;
AuthenticationManager 接口:認(rèn)證時(shí)主要是PrividerManager 實(shí)現(xiàn)類(lèi)去做認(rèn)證;

PrividerManager 實(shí)現(xiàn)類(lèi)中主要的方法和屬性介紹:
認(rèn)證器集合:providers

authenticate 方法:

1. 遍歷認(rèn)證器.
2.判斷認(rèn)證器是否支持token的認(rèn)證
3.如果支持,進(jìn)行具體的認(rèn)證邏輯
AuthenticationProvider 接口:

AbstractUserDetailsAuthenticationProvider 抽象類(lèi):
authenticate 方法:

子類(lèi)實(shí)現(xiàn)retrieveUser 方法,通過(guò)不同的方式獲取UserDetails;
DaoAuthenticationProvider 實(shí)現(xiàn)類(lèi)(去實(shí)現(xiàn)retrieveUser ):
retrieveUser方法:

通過(guò)UserDetailsService 對(duì)象獲取UserDetails對(duì)象;
UserDetailsService? 屬性:

UserDetailsService 接口:
spring-boot-starter-security包下:

spring-security-oauth2包下:

可以看出在spring-security-oauth2包下多一個(gè)ClientDetailsUserDetailsService類(lèi),這個(gè)也就是spring security實(shí)現(xiàn)Oauth2的主要認(rèn)證類(lèi);