前言:本篇是自己通過看代碼及網上的一些博客,總結整理的記錄,供大家參考。
一,HttpSecurity的本質
@Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception {return http.antMatcher("/**").authorizeRequests(authorize -> authorize.anyRequest().authenticated()).build(); }
其實就能夠知道HttpSecurity
是用來構建包含了一系列過濾器鏈的過濾器SecurityFilterChain
,平常我們的配置就是圍繞構建SecurityFilterChain
進行,看下面這張老圖:
從上面這個圖中可以看出構建好的還要交給FilterChainProxy
來代理,是不是有點多此一舉?
二,WebSecurity的本質
在有些情況下這種確實多此一舉, 不過更多時候我們可能需要配置多個SecurityFilterChain
來實現對多種訪問控制策略。
爲了精細化的管理多個SecurityFilterChain
的生命週期,搞一個統一管理這些SecurityFilterChain
的代理就十分必要了,這就是WebSecurity
的意義。下面是WebSecurity
的build
方法的底層邏輯:
@Override protected Filter performBuild() throws Exception {Assert.state(!this.securityFilterChainBuilders.isEmpty(),() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "+ "Typically this is done by exposing a SecurityFilterChain bean "+ "or by adding a @Configuration that extends WebSecurityConfigurerAdapter. "+ "More advanced users can invoke " + WebSecurity.class.getSimpleName()+ ".addSecurityFilterChainBuilder directly");// 被忽略請求的個數 和 httpscurity的個數 構成了過濾器鏈集合的大小int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);// 初始化過濾器鏈集合中的 忽略請求過濾器鏈 for (RequestMatcher ignoredRequest : this.ignoredRequests) {securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));}// 初始化過濾器鏈集合中的 httpsecurity定義的過濾器鏈for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {securityFilterChains.add(securityFilterChainBuilder.build());}FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);if (this.httpFirewall != null) {// 請求防火牆filterChainProxy.setFirewall(this.httpFirewall);}if (this.requestRejectedHandler != null) {// 請求拒絕處理器filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);}filterChainProxy.afterPropertiesSet();Filter result = filterChainProxy;if (this.debugEnabled) {this.logger.warn("\n\n" + "********************************************************************\n"+ "********** Security debugging is enabled. *************\n"+ "********** This may include sensitive information. *************\n"+ "********** Do not use in a production system! *************\n"+ "********************************************************************\n\n");result = new DebugFilter(filterChainProxy);}this.postBuildAction.run();return result; }
從上面中的源碼可以看出,WebSecurity
用來構建一個名爲springSecurityFilterChain
的Spring BeanFilterChainProxy
。它的作用是來定義哪些請求忽略安全控制,哪些請求必須安全控制,在合適的時候清除SecurityContext
以避免內存泄漏,同時也可以用來定義請求防火牆和請求拒絕處理器,另外我們開啓Spring Seuciry Debug模式也是這裏配置的。
同時還有一個作用可能是其它文章沒有提及的,FilterChainProxy
是Spring Security對Spring framework應用的唯一出口,然後通過它與一個Servlet在Spring的橋接代理DelegatingFilterProxy
結合構成Spring對Servlet體系的唯一出口。這樣就將Spring Security、Spring framework、Servlet API三者隔離了起來。
我們事實上可以認爲,WebSecurity
是Spring Security對外的唯一出口,而HttpSecurity
只是內部安全策略的定義方式;
WebSecurity主要構建
FilterChainProxy
,而HttpSecurity
則構建SecurityFilterChain
,另外它們的父類都是AbstractConfiguredSecurityBuilder