Spring Security(2):過濾器鏈(filter chain)的介紹

上一節中,主要講了Spring Security認證和受權的核心組件及核心方法。可是,何時調用這些方法呢?答案就是Filter和AOP。Spring Security在咱們進行用戶認證以及授予權限的時候,經過各類各樣的攔截器來控制權限的訪問。
對於基於HttpRequest的方式對端點進行保護,咱們使用一個Filter Chain來保護;對於基於方法調用進行保護,咱們使用AOP來保護。本篇重點講Spring Security中過濾器鏈的種類及過濾器中如何實現的認證和受權。web

 

Spring Security會默認爲咱們添加15個過濾器,咱們能夠從WebSecurity(WebSecurity是Spring Security加載的一個重要對象,將在下節具體講述)的performBuild()方法中看到過濾器鏈SecurityFilterChain的構建過程,並交由FilterChainProxy對象代理。咱們從SecurityFilterChain的默認實現類DefaultSecurityFilterChain中的log看出,Spring Security由如下過濾器組成了過濾器鏈:spring

Creating filter chain: any request, [
  org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@7f353a0f,
  org.springframework.security.web.context.SecurityContextPersistenceFilter@4735d6e5,
  org.springframework.security.web.header.HeaderWriterFilter@314a31b0,
  org.springframework.security.web.csrf.CsrfFilter@4ef2ab73,
  org.springframework.security.web.authentication.logout.LogoutFilter@57efc6fd,
  org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@d88f893,
  org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@2cd388f5,
  org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@7ea2412c,
  org.springframework.security.web.authentication.www.BasicAuthenticationFilter@2091833,
  org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4dad0eed,
  org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@16132f21,
  org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1c93b51e,
  org.springframework.security.web.session.SessionManagementFilter@59edb4f5,
  org.springframework.security.web.access.ExceptionTranslationFilter@104dc1a2,
  org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1de0641b
]

 

下面就是各個過濾器的功能,其中SecurityContextPersistenceFilter,UsernamePasswordAuthenticationFilter及FilterSecurityInterceptor分別對應了上節SecurityContext,AuthenticationManager,AccessDecisionManager的處理。api

[WebAsyncManagerIntegrationFilter] (異步方式)提供了對securityContext和WebAsyncManager的集成。方式是經過SecurityContextCallableProcessingInterceptor的beforeConcurrentHandling(NativeWebRequest, Callable)方法來將SecurityContext設置到Callable上。其實就是把SecurityContext設置到異步線程中,使其也能獲取到用戶上下文認證信息。緩存

 

[SecurityContextPersistenceFilter] (同步方式)在請求以前從SecurityContextRepository(默認實現是HttpSessionSecurityContextRepository)獲取信息並填充SecurityContextHolder(若是沒有,則建立一個新的ThreadLocal的SecurityContext),並在請求完成並清空SecurityContextHolder並更新SecurityContextRepository。安全

在Spring Security中,雖然安全上下文信息被存儲於Session中,但實際的Filter中不該直接操做Session(過濾器通常負責核心的處理流程,而具體的業務實現,一般交給其中聚合的其餘實體類),而是用如HttpSessionSecurityContextRepository中loadContext(),saveContext()來存取session。session

 

[HeaderWriterFilter] 用來給http響應添加一些Header,好比X-Frame-Options,X-XSS-Protection*,X-Content-Type-Options。app

 

[CsrfFilter] 默認開啓,用於防止csrf攻擊的過濾器異步

 

[LogoutFilter] 處理註銷的過濾器async

 

[UsernamePasswordAuthenticationFilter] 表單提交了username和password,被封裝成UsernamePasswordAuthenticationToken對象進行一系列的認證,即是主要經過這個過濾器完成的,即調用AuthenticationManager.authenticate()。在表單認證的方法中,這是最最關鍵的過濾器。具體過程是:ide

(1)調用AbstractAuthenticationProcessingFilter.doFilter()方法執行過濾器

(2)調用UsernamePasswordAuthenticationFilter.attemptAuthentication()方法

(3)調用AuthenticationManager.authenticate()方法(實際上委託給AuthenticationProvider的實現類來處理)

 

[DefaultLoginPageGeneratingFilter] & [DefaultLogoutPageGeneratingFilter] 若是沒有配置/login及login page, 系統則會自動配置這兩個Filter。


[BasicAuthenticationFilter] Processes a HTTP request's BASIC authorization headers, putting the result into the SecurityContextHolder.

 

[RequestCacheAwareFilter] 內部維護了一個RequestCache,用於緩存request請求

 

[SecurityContextHolderAwareRequestFilter] 此過濾器對ServletRequest進行了一次包裝,使得request具備更加豐富的API(populates the ServletRequest with a request wrapper which implements servlet API security methods)

 

[AnonymousAuthenticationFilter] 匿名身份過濾器,spring security爲了兼容未登陸的訪問,也走了一套認證流程,只不過是一個匿名的身份。它位於身份認證過濾器(e.g. UsernamePasswordAuthenticationFilter)以後,意味着只有在上述身份過濾器執行完畢後,SecurityContext依舊沒有用戶信息,AnonymousAuthenticationFilter該過濾器纔會有意義。

 

[SessionManagementFilter] 和session相關的過濾器,內部維護了一個SessionAuthenticationStrategy來執行任何與session相關的活動,好比session-fixation protection mechanisms or checking for multiple concurrent logins。

 

[ExceptionTranslationFilter] 異常轉換過濾器,這個過濾器自己不處理異常,而是將認證過程當中出現的異常(AccessDeniedException and AuthenticationException)交給內部維護的一些類去處理。它
位於整個springSecurityFilterChain的後方,用來轉換整個鏈路中出現的異常,將其轉化,顧名思義,轉化以意味自己並不處理。通常其只處理兩大類異常:AccessDeniedException訪問異常和AuthenticationException認證異常。

它將Java中的異常和HTTP的響應鏈接在了一塊兒,這樣在處理異常時,咱們不用考慮密碼錯誤該跳到什麼頁面,帳號鎖定該如何,只須要關注本身的業務邏輯,拋出相應的異常即可。若是該過濾器檢測到AuthenticationException,則將會交給內部的AuthenticationEntryPoint去處理,若是檢測到AccessDeniedException,須要先判斷當前用戶是否是匿名用戶,若是是匿名訪問,則和前面同樣運行AuthenticationEntryPoint,不然會委託給AccessDeniedHandler去處理,而AccessDeniedHandler的默認實現,是AccessDeniedHandlerImpl。

 

[FilterSecurityInterceptor] 這個過濾器決定了訪問特定路徑應該具有的權限,這些受限的資源訪須要什麼權限或角色,這些判斷和處理都是由該類進行的。

(1)調用FilterSecurityInterceptor.invoke()方法執行過濾器

(2)調用AbstractSecurityInterceptor.beforeInvocation()方法

(3)調用AccessDecisionManager.decide()方法決策判斷是否有該權限

相關文章
相關標籤/搜索