Spring Security認證簡介

認證簡介

認證過程

  1. 用戶使用用戶名和密碼進行登陸。
  2. Spring Security 將獲取到的用戶名和密碼封裝成一個實現了 Authentication 接口的 UsernamePasswordAuthenticationToken。
  3. 將上述產生的 token 對象傳遞給 AuthenticationManager 進行登陸認證。
  4. AuthenticationManager 認證成功後將會返回一個封裝了用戶權限等信息的 Authentication 對象。
  5. 經過調用 SecurityContextHolder.getContext().setAuthentication(...) 將 AuthenticationManager 返回的 Authentication 對象賦予給當前的 SecurityContext。

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

Web 應用的認證過程

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

  1. 引導用戶進行登陸,一般是重定向到一個基於 form 表單進行登陸的頁面,具體視配置而定。
  2. 用戶輸入用戶名和密碼後請求認證,後臺仍是會像上節描述的那樣獲取用戶名和密碼封裝成一個 UsernamePasswordAuthenticationToken 對象,而後把它傳遞給 AuthenticationManager 進行認證。
  3. 若是認證失敗將繼續執行步驟 1,若是認證成功則會保存返回的 Authentication 到 SecurityContext,而後默認會將用戶重定向到以前訪問的頁面。
  4. 用戶登陸認證成功後再次訪問以前受保護的資源時就會對用戶進行權限鑑定,如不存在對應的訪問權限,則會返回 403 錯誤碼。

在上述步驟中將有不少不一樣的類參與,但其中主要的參與者是 ExceptionTranslationFilter。3d

ExceptionTranslationFilter

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

在 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 對象了,因此下次訪問的時候也就再也不須要進行登陸認證了。對象

相關文章
相關標籤/搜索