如何分析Spring Security中過濾器鏈的配置問題,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站、網(wǎng)站重做改版、武城網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5開發(fā)、電子商務(wù)商城網(wǎng)站建設(shè)、集團公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為武城等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
首先這個問題本身是有點問題的,因為 http.authorizeRequests()
并非總是第一個,雖然大部分情況下,我們看到的是第一個,但是也有很多情況 http.authorizeRequests()
不是首先出現(xiàn)。要搞明白這個問題,我們就要搞清楚 http.authorizeRequests()
到底是啥意思!
這就涉及到 Spring Security 中過濾器鏈的配置問題
即使大家沒有仔細(xì)研究過 Spring Security 中認(rèn)證、授權(quán)功能的實現(xiàn)機制,大概也都多多少少聽說過 Spring Security 這些功能是通過過濾器來實現(xiàn)的。
是的,沒錯!Spring Security 中一共提供了 32 個過濾器,其中默認(rèn)使用的有 15 個,這些過濾器松哥在以后的文章中再和大家細(xì)說,今天我們就先來看看過濾器的配置問題。
在一個 Web 項目中,請求流程大概如下圖所示:
請求從客戶端發(fā)起(例如瀏覽器),然后穿過層層 Filter,最終來到 Servlet 上,被 Servlet 所處理。
那有小伙伴要問了,Spring Security 中默認(rèn)的 15 個過濾器就是這樣嵌套在 Client 和 Servlet 之間嗎?
不是的!
上圖中的 Filter 我們可以稱之為 Web Filter,Spring Security 中的 Filter 我們可以稱之為 Security Filter,它們之間的關(guān)系如下圖:
可以看到,Spring Security Filter 并不是直接嵌入到 Web Filter 中的,而是通過 FilterChainProxy 來統(tǒng)一管理 Spring Security Filter,F(xiàn)ilterChainProxy 本身則通過 Spring 提供的 DelegatingFilterProxy 代理過濾器嵌入到 Web Filter 之中。
?DelegatingFilterProxy 很多小伙伴應(yīng)該比較熟悉,在 Spring 中手工整合 Spring Session、Shiro 等工具時都離不開它,現(xiàn)在用了 Spring Boot,很多事情 Spring Boot 幫我們做了,所以有時候會感覺 DelegatingFilterProxy 的存在感有所降低,實際上它一直都在。
上面和大家介紹的是單個過濾器鏈,實際上,在 Spring Security 中,可能存在多個過濾器鏈。
在松哥前面講 OAuth3 系列的時候,有涉及到多個過濾器鏈,但是一直沒有拎出來單獨講過,今天就來和大家分享一下。
有人會問,下面這種配置是不是就是多個過濾器鏈?
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated()
...
.csrf().disable();
}
這樣的配置相信大家都見過,但是這并不是多個過濾器鏈,這是一個過濾器鏈。因為不管是 /admin/**
還是 /user/**
,走過的過濾器都是一樣的,只是不同的路徑判斷條件不一樣而已。
如果系統(tǒng)存在多個過濾器鏈,多個過濾器鏈會在 FilterChainProxy 中進行劃分,如下圖:
可以看到,當(dāng)請求到達 FilterChainProxy 之后,F(xiàn)ilterChainProxy 會根據(jù)請求的路徑,將請求轉(zhuǎn)發(fā)到不同的 Spring Security Filters 上面去,不同的 Spring Security Filters 對應(yīng)了不同的過濾器,也就是不同的請求將經(jīng)過不同的過濾器。
正常情況下,我們配置的都是一個過濾器鏈,多個過濾器鏈怎么配置呢?松哥給大家一個舉一個簡單的例子:
@Configuration
public class SecurityConfig {
@Bean
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("javaboy").password("{bcrypt}$2a$10$Sb1gAUH4wwazfNiqflKZve4Ubh.spJcxgHG8Cp29DeGya5zsHENqi").roles("admin", "aaa", "bbb").build());
manager.createUser(User.withUsername("sang").password("{noop}123").roles("admin").build());
manager.createUser(User.withUsername("江南一點雨").password("{MD5}{Wucj/L8wMTMzFi3oBKWsETNeXbMFaHZW9vCK9mahMHc=}4d43db282b36d7f0421498fdc693f2a2").roles("user", "aaa", "bbb").build());
return manager;
}
@Configuration
@Order(1)
static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/foo/**")
.authorizeRequests()
.anyRequest().hasRole("admin")
.and()
.csrf().disable();
}
}
@Configuration
@Order(2)
static class DefaultWebSecurityConfig2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/bar/**")
.authorizeRequests()
.anyRequest().hasRole("user")
.and()
.formLogin()
.permitAll()
.and()
.csrf().disable();
}
}
}
http.authorizeRequests()
開始,
http.authorizeRequests()
配置表示該過濾器鏈過濾的路徑是
/**
。在靜態(tài)內(nèi)部類里邊,我是用了
http.antMatcher("/bar/**")
開啟配置,表示將當(dāng)前過濾器鏈的攔截范圍限定在
/bar/**
。從上面這段代碼中大家可以看到,configure(HttpSecurity http) 方法似乎就是在配置過濾器鏈?是的沒錯!我們在該方法中的配置,都是在添加/移除/修改 Spring Security 默認(rèn)提供的過濾器,所以該方法就是在配置 Spring Security 中的過濾器鏈,至于是怎么配置的,松哥以后抽時間再來和大家細(xì)說。
最后,我們在回到一開始小伙伴提的問題。
首先,http.authorizeRequests()
配置并非總在第一行出現(xiàn),如果只有一個過濾器鏈,他總是在第一行出現(xiàn),表示該過濾器鏈的攔截規(guī)則是 /**
(請求只有先被過濾器鏈攔截下來,接下來才會進入到不同的 Security Filters 中進行處理),如果存在多個過濾器鏈,就不一定了。
僅僅從字面意思來理解,authorizeRequests() 方法的返回值是 ExpressionUrlAuthorizationConfigurer.antMatchers("/admin/**").hasRole("admin").antMatchers("/user/**").hasRole("user")
。
看完上述內(nèi)容,你們掌握如何分析Spring Security中過濾器鏈的配置問題的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!