1. 程式人生 > >Spring Security 認證過程

Spring Security 認證過程

3.1 username 但是 用戶 請求 應用 並且 其它 exce

目錄

1.1 認證過程

1.2 Web應用的認證過程

1.2.1 ExceptionTranslationFilter

1.2.2 在request之間共享SecurityContext

1.1 認證過程

1、用戶使用用戶名和密碼進行登錄。

2、Spring Security將獲取到的用戶名和密碼封裝成一個實現了Authentication接口的UsernamePasswordAuthenticationToken。

3、將上述產生的token對象傳遞給AuthenticationManager進行登錄認證。

4、AuthenticationManager認證成功後將會返回一個封裝了用戶權限等信息的Authentication對象。

5、通過調用SecurityContextHolder.getContext().setAuthentication(...)將AuthenticationManager返回的Authentication對象賦予給當前的SecurityContext。

上述介紹的就是Spring Security的認證過程。在認證成功後,用戶就可以繼續操作去訪問其它受保護的資源了,但是在訪問的時候將會使用保存在SecurityContext中的Authentication對象進行相關的權限鑒定。

1.2 Web應用的認證過程

如果用戶直接訪問登錄頁面,那麽認證過程跟上節描述的基本一致,只是在認證完成後將跳轉到指定的成功頁面,默認是應用的根路徑。如果用戶直接訪問一個受保護的資源,那麽認證過程將如下:

1、引導用戶進行登錄,通常是重定向到一個基於form表單進行登錄的頁面,具體視配置而定。

2、用戶輸入用戶名和密碼後請求認證,後臺還是會像上節描述的那樣獲取用戶名和密碼封裝成一個UsernamePasswordAuthenticationToken對象,然後把它傳遞給AuthenticationManager進行認證。

3、如果認證失敗將繼續執行步驟1,如果認證成功則會保存返回的Authentication到SecurityContext,然後默認會將用戶重定向到之前訪問的頁面。

4、用戶登錄認證成功後再次訪問之前受保護的資源時就會對用戶進行權限鑒定,如不存在對應的訪問權限,則會返回403錯誤碼。

在上述步驟中將有很多不同的類參與,但其中主要的參與者是ExceptionTranslationFilter。

1.2.1 ExceptionTranslationFilter

ExceptionTranslationFilter是用來處理來自AbstractSecurityInterceptor拋出的AuthenticationException和AccessDeniedException的。AbstractSecurityInterceptor是Spring Security用於攔截請求進行權限鑒定的,其擁有兩個具體的子類,攔截方法調用的MethodSecurityInterceptor和攔截URL請求的FilterSecurityInterceptor。當ExceptionTranslationFilter捕獲到的是AuthenticationException時將調用AuthenticationEntryPoint引導用戶進行登錄;如果捕獲的是AccessDeniedException,但是用戶還沒有通過認證,則調用AuthenticationEntryPoint引導用戶進行登錄認證,否則將返回一個表示不存在對應權限的403錯誤碼。

1.2.2 在request之間共享SecurityContext

可能你早就有這麽一個疑問了,既然SecurityContext是存放在ThreadLocal中的,而且在每次權限鑒定的時候都是從ThreadLocal中獲取SecurityContext中對應的Authentication所擁有的權限,並且不同的request是不同的線程,為什麽每次都可以從ThreadLocal中獲取到當前用戶對應的SecurityContext呢?在Web應用中這是通過SecurityContextPersistentFilter實現的,默認情況下其會在每次請求開始的時候從session中獲取SecurityContext,然後把它設置給SecurityContextHolder,在請求結束後又會將SecurityContextHolder所持有的SecurityContext保存在session中,並且清除SecurityContextHolder所持有的SecurityContext。這樣當我們第一次訪問系統的時候,SecurityContextHolder所持有的SecurityContext肯定是空的,待我們登錄成功後,SecurityContextHolder所持有的SecurityContext就不是空的了,且包含有認證成功的Authentication對象,待請求結束後我們就會將SecurityContext存在session中,等到下次請求的時候就可以從session中獲取到該SecurityContext並把它賦予給SecurityContextHolder了,由於SecurityContextHolder已經持有認證過的Authentication對象了,所以下次訪問的時候也就不再需要進行登錄認證了。

(註:本文是基於Spring Security3.1.6所寫)

Spring Security 認證過程