Spring Security 認證簡介

2018-09-28 19:19 更新

認證簡介

認證過程

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

上述介紹的就是 Spring Security 的認證過程。在認證成功后,用戶就可以繼續(xù)操作去訪問其它受保護的資源了,但是在訪問的時候?qū)褂帽4嬖?SecurityContext 中的 Authentication 對象進行相關的權限鑒定。

Web 應用的認證過程

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

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

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

ExceptionTranslationFilter

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

在 request 之間共享 SecurityContext

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

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號