Spring Security 總體結構概覽

Spring Security 概覽

Spring Security的功能能夠歸納爲兩部分,即認證和受權。html

認證就是一個用戶使用令牌(最多見的是帳號和密碼)登錄,服務器驗證這個用戶的令牌是否有效。html5

受權則是認證以後,系統根據這個用戶的信息判斷他擁有哪些權限,能訪問哪一種資源,能對資源進何種操做,並向他授予相關的權限,對沒有權限訪問的用戶進行阻止。java

這裏說的Spring Security是基於Servlet容器的。web

從Filter提及

Spring Security的Servlet支持是基於Servlet的Filter的。Filter能夠對請求進行處理,但Filter通常會將處理好的請求交給FilterChain中的下一個Filter,即一個個Filter按照相應的順序組合起來造成了一個Filter鏈,從而達到對請求進行過濾/提早處理的效果。spring

FilterChain

當請求到達時,Servlet容器會初始化一個FilterChain,並將請求傳遞到裏面進行處理:api

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // do something before the rest of the application
    chain.doFilter(request, response); // invoke the rest of the application
    // do something after the rest of the application
}
複製代碼

通過一個個Filter處理後請求才到達Servlet處理並響應,因而可知,Filter在FilterChain中組織的順序很是重要。安全

DelegatingFilterProxy

由於Servlet容器跟Spring的IoC容器是兩種不一樣的容器,Servlet容器沒法獲知Spring容器中各類Bean(用戶自定義Filter)的信息,也沒法直接使用這些Bean(Filter),因此須要在二者間創建橋樑,使得咱們定義的Bean(Filter)可以被Servlet容器使用。服務器

Spring提供了一種叫DelegatingFilterProxy的Filter實現。app

DelegatingFilterProxy

它像普通的Filter同樣被插入到FilterChain中,它的功能是將請求委託給Spring容器裏的Bean Filter來處理,從而創建起Servlet容器和Spring容器之間的橋樑。性能

例如圖中DelegatingFilterProxy會在Spring容器中尋找Bean Filter0,並將ServletRequestServletResponse傳遞過去:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // Lazily get Filter that was registered as a Spring Bean
    // For the example in DelegatingFilterProxy delegate is an instance of Bean Filter0
    Filter delegate = getFilterBean(someBeanName);
    // delegate work to the Spring Bean
    delegate.doFilter(request, response);
}
複製代碼

DelegatingFilterProxy的另外一個好處是它能夠延遲加載Bean Filter實例,由於FilterChain會在Servlet容器啓動前初始化,這樣能夠提高Servlet容器啓動的性能。

FilterChainProxy

上面提到DelegatingFilterProxy會將請求委託給Bean Filter,而其實這裏的Bean Filter也不會直接處理請求,會將請求進一步轉發,這個Bean Filter便是FilterChainProxy

FilterChainProxy是Spring Security提供的特殊Filter,它會將請求委託到另外一種FilterChain中,即Spring的FilterChain:SecurityFilterChain

SecurityFilterChain

咱們能夠很天然地想到,SecurityFilterChain中即是Spring的Bean Filter了,即SecurityFilter

SecurityFilter

這裏的SecurityFilter就是普通的Bean,他們能夠識別本身能處理的請求並對請求處理,不然將請求傳給鏈中的下一個Filter,例如最多見的UsernamePasswordAuthenticationFilter能夠識別處理基於表單的登錄請求。

值得注意的是,SecurityFilterChain能夠有多條,能夠根據不一樣的請求來判斷請求應該被傳遞到哪一個SecurityFilterChain中:

好比符合/api/**匹配模式的URL應該被傳遞到最上面的SecurityFilterChain中,這個請求一旦匹配到了某個上游的SecurityFilterChain,下游的SecurityFilterChain就不會再進行匹配。

Many SecurityFilterChains

有哪些Security Filter?

官方文檔給出了按照Spring Security Filter排列順序的列表:

Security Filters

處理安全異常

ExceptionTranslationFilter容許將AccessDeniedExceptionAuthenticationException異常轉換爲HTTP響應,從它的名字能夠看到,它也是一個Filter,能夠被插入到SecurityFilterChain中,這是它的工做流程:

ExceptionTanslationFilter

  1. 它調用下層的Filter處理請求
  2. 若是下層Filter拋出AuthenticationException,則會被它捕獲(見下面代碼),並調用它的startAuthentication()方法跳轉進行認證。(圖中的SecurityContextHolder等幾個東西屬於認證功能部分,能夠先不用管)
  3. 若是下層Filter拋出AccessDeniedException則對異常做出響應,通知用戶禁止訪問。

總結

從上面能夠看到,Spring Security的功能是經過Filter來實現的。每一個Filter都是一個Bean,用戶經過配置不一樣的Filter或自行實現Filter來達到保護應用/認證/受權等目的,不一樣的Filter組成了多個FilterChain,來實現不一樣的要求。

參考資料:Spring Security Reference - Version 5.3.2.RELEASE

相關文章
相關標籤/搜索