您好,登錄后才能下訂單哦!
這篇文章主要介紹Spring Security過濾器鏈加載執行流程的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
Spring Security 采用 IoC 和 AOP思想,基于 Servlet 過濾器實現的安全框架、為 Web 請求和方法調用提供身份確認和授權處理,還提供與其他庫的集成以簡化其使用,避免了代碼耦合,減少了大量重復代碼工作。
在之前 web.xml中,我們是這樣寫的。
<!--SpringSecurity核心過濾器鏈--> <!--springSecurityFilterChain名詞不能修改--> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
在 Spring Boot項目之后,我們引入 Spring Security依賴,什么也沒做,啟動項目 Spring Security 就會生效,訪問請求就進行了攔截。
Spring Boot 對于 Spring Security 提供了自動化配置方案,可以使用更少的配置來使用 Spring Security。
那么這個過濾器鏈是怎么加載和實現攔截的呢?
當 Spring Boot 項目啟動后,SecurityFilterAutoConfiguration類會加載 DelegatingFilterProxyRegistrationBean注冊過濾器,名字為 springSecurityFilterChain。
注意:
springSecurityFilterChain名字是固定寫死的。
DelegatingFilterProxyRegistrationBean 注冊成功后,該過濾器就被加載了到了注冊器中。
注冊器注冊了所有的過濾器后,會為每個過濾器生成 DelegatingFilterProxy代理對象并注冊到 IoC中 。
我們訪問項目,就會進入 DelegatingFilterProxy類的 doFilter方法。
DelegatingFilterProxy類
本質也是一個 Filter,其間接實現了 Filter接口,但是在 doFilter中其實調用的從 Spring 容器中獲取到的代理 Filter的實現類。
返回的 FilterChainProxy對象。
由此可知,DelegatingFilterProxy類通過 springSecurityFilterChain這個名稱,得到了一個 FilterChainProxy過濾器,最終執行的是這個過濾器的 doFilter方法。
1)驗證 springSecurityFilterChain名詞不能修改
查看 initDelegate方法。
FilterChainProxy類
本質也是一個 Filter,所以查看 doFilter方法。留意該類里面的屬性。
public class FilterChainProxy extends GenericFilterBean { private static final Log logger = LogFactory.getLog(FilterChainProxy.class); private static final String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED"); // 過濾器鏈 private List<SecurityFilterChain> filterChains; private FilterChainProxy.FilterChainValidator filterChainValidator; private HttpFirewall firewall;
驚不驚喜?15個過濾器都在這里了!
原來這些過濾器都被封裝進 SecurityFilterChain對象中。
SecurityFilterChain類
是個接口,實現類也只有一個 DefaultSecurityFilterChain類
。
DefaultSecurityFilterChain類的構造方法,初始化了 List filters,是通過傳參放進去的。
過濾器鏈參數是什么時候傳入的?
創建 Spring Security 過濾器鏈是交給 Spring boot 自動配置,由 SpringBootWebSecurityConfiguration類
創建注入。
查看 WebSecurityConfigurerAdapter類。
然后會注入 HttpSecurity對象,HttpSecurity可以理解為 Spring Security 的 http核心配置,存放 Spring Security 中的過濾器鏈、請求匹配路徑等相關認證授權的重要方法。
然后開始創建 Spring Security 過濾器鏈了,是交給 Spring Boot自動配置,一共有 15個過濾器。
使用 OrderedFilter進行代理,并設置了order屬性。
添加完成后,將這些過濾器再封裝為 DefaultSecurityFilterChain對象。
最后通過 WebSecurityConfiguration配置加載 springSecurityFilterChain,WebSecurityConfiguration中維護了securityFilterChains屬性,會存放過濾器鏈中所有的過濾器。
總結:
Spring boot 通過 DelegatingFilterProxyRegistrationBean注冊過濾器,名字為 springSecurityFilterChain,并生成 DelegatingFilterProxy代理對象并注冊到 IoC中。最終真正調用 FilterChainProxy過濾器的 doFilter 獲取到 Spring Security 過濾器鏈。
Spring Security的過濾器鏈在底層是封裝在 SecurityFilterChain接口中的。
首先進入的是 OncePerRequestFilter 過濾器。
OncePerRequestFilter是為了確保一次請求中只通過一次filter,而不需要重復的執行。
會進入 DelegatingFilterProxy代理對象中 invokeDelegate方法,實際真正執行的是 FilterChainProxy過濾器的 doFilter 方法。
查看 FilterChainProxy過濾器中的 doFilterInternal方法。
然后首先進入FilterChainProxy中的 doFilterInternal方法。
doFilterInternal方法中會調用 getFilters方法,會從過濾器鏈中拿出所有的攔截器。
然后創建一個 VirtualFilterChain對象,一個虛擬的過濾器鏈,并執行其中的 doFilter 方法。使用過濾器對當前請求進行層層過濾。
最后進入到 FilterSecurityInterceptor過濾器中,該過濾器是過濾器鏈的最后一個過濾器,invoke方法中。
先調用父類的 beforeInvocation方法,之后調用 filterChain的 doFilter方法,之后調用父類的 finallyInvocation和afterInvocation方法。
在 beforeInvocation方法中,如果當前的請求沒有通過認證,會拋出 Access is denied異常,這個異常會被ExceptionTranslationFilter過濾器處理。如果拋出的異常是 AuthenticationException,則執行方法sendStartAuthentication方法。
最終調用 EntryPoint的 commence方法,發布異常。
1、WebAsyncManagerIntegrationFilter
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
其主要用于集成 SecurityContext到 Spring異步執行機制中的 WebAsyncManager。
2、SecurityContextPersistenceFilter
org.springframework.security.web.context.SecurityContextPersistenceFilter
其主要是使用 SecurityContextRepository在 session中保存或更新一個SecurityContext,并將 SecurityContext給以后的過濾器使用,來為后續 filter建立所需的上下文。SecurityContext
中存儲了當前用戶的認證以及權限信息。
3、HeaderWriterFilter
org.springframework.security.web.header.HeaderWriterFilter
其主要是向請求的 Header中添加相應的信息,可在 http標簽內部使用 security:headers來控制。
4、CsrfFilter
org.springframework.security.web.csrf.CsrfFilter
csrf又稱跨域請求偽造
,SpringSecurity會對所有 post請求驗證是否包含系統生成的 csrf的 token信息,
如果不包含,則報錯。起到防止csrf攻擊的效果。
5、LogoutFilter
org.springframework.security.web.authentication.logout.LogoutFilter
其主要用于實現用戶退出,清除認證信息。默認匹配 URL為 /logout的請求。
6、UsernamePasswordAuthenticationFilter
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
其主要用于認證操作,默認匹配URL為 /login且必須為POST請求。
7、DefaultLoginPageGeneratingFilter
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
如果沒有在配置文件中指定認證頁面,則由該過濾器生成一個默認認證頁面。
8、DefaultLogoutPageGeneratingFilter
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
由此過濾器可以生產一個默認的退出登錄頁面
9、BasicAuthenticationFilter
org.springframework.security.web.authentication.www.BasicAuthenticationFilter
此過濾器會自動解析 HTTP請求中頭部名字為 Authentication,且以 Basic開頭的頭信息。
10、RequestCacheAwareFilter
org.springframework.security.web.savedrequest.RequestCacheAwareFilter
通過HttpSessionRequestCache內部維護了一個 RequestCache,用于緩存 HttpServletRequest。
11、SecurityContextHolderAwareRequestFilter
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
針對 ServletRequest進行了一次包裝,使得 request具有更加豐富的 API。
12、AnonymousAuthenticationFilter
org.springframework.security.web.authentication.AnonymousAuthenticationFilter
當 SecurityContextHolder中認證信息為空,則會創建一個匿名用戶
存入到 SecurityContextHolder中。
Spring Security為了兼容未登錄的訪問,也走了一套認證流程,只不過是一個匿名的身份。
13、SessionManagementFilter
org.springframework.security.web.session.SessionManagementFilter
其主要用于限制同一用戶開啟多個會話的數量。
14、ExceptionTranslationFilter
org.springframework.security.web.access.ExceptionTranslationFilter
異常轉換過濾器位于整個 springSecurityFilterChain的后方,用來轉換整個鏈路中出現的異常。ExceptionTranslationFilter過濾器會攔截處理 AccessDeniedException和 AuthenticationException并添加到HTTP響應中。
15、FilterSecurityInterceptor
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
獲取所配置資源訪問的授權信息,根據 SecurityContextHolder中存儲的用戶信息來決定其是否有權限。
以上是“Spring Security過濾器鏈加載執行流程的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。