Spring Security 實戰(zhàn)干貨:WebSecurity和HttpSecurity的關系
前幾天有粉絲私信我:WebSecurity和HttpSecurity啥關系?當時給我問住了,我大概只知道它們之間的關系類似TypeScript和JavaScript的關系,但是具體的細節(jié)確實不太清楚。因此就在周末簡單研究了一下。
HttpSecurity的本質(zhì)
前幾天在Spring Security 5.4的新玩法中介紹了一種新的配置HttpSecurity的方式:
- @Bean
 - SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
 - return http
 - .antMatcher("/**")
 - .authorizeRequests(authorize -> authorize
 - .anyRequest().authenticated()
 - )
 - .build();
 - }
 
其實就能夠知道HttpSecurity是用來構建包含了一系列過濾器鏈的過濾器SecurityFilterChain,平常我們的配置就是圍繞構建SecurityFilterChain進行。還得拿出這張老圖:
安全過濾鏈
從上面這個圖中可以看出構建好的還要交給FilterChainProxy來代理,是不是有點多此一舉?
WebSecurity的本質(zhì)
在有些情況下這種確實多此一舉, 不過更多時候我們可能需要配置多個SecurityFilterChain來實現(xiàn)對多種訪問控制策略。
多個SecurityFilterChain
為了精細化的管理多個SecurityFilterChain的生命周期,搞一個統(tǒng)一管理這些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");
 - // 被忽略請求的個數(shù) 和 httpscurity的個數(shù) 構成了過濾器鏈集合的大小
 - 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以避免內(nèi)存泄漏,同時也可以用來定義請求防火墻和請求拒絕處理器,另外我們開啟Spring Seuciry Debug模式也是這里配置的。
同時還有一個作用可能是其它文章沒有提及的,F(xiàn)ilterChainProxy是Spring Security對Spring framework應用的唯一出口,然后通過它與一個Servlet在Spring的橋接代理DelegatingFilterProxy結合構成Spring對Servlet體系的唯一出口。這樣就將Spring Security、Spring framework、Servlet API三者隔離了起來。
總結
我們事實上可以認為,WebSecurity是Spring Security對外的唯一出口,而HttpSecurity只是內(nèi)部安全策略的定義方式;WebSecurity對標FilterChainProxy,而HttpSecurity則對標SecurityFilterChain,另外它們的父類都是AbstractConfiguredSecurityBuilder。掌握了這些基本上你就能知道它們之間的區(qū)別是什么了。
本文轉(zhuǎn)載自微信公眾號「碼農(nóng)小胖哥」,可以通過以下二維碼關注。轉(zhuǎn)載本文請聯(lián)系碼農(nóng)小胖哥公眾號。


















 
 
 












 
 
 
 