您好,登錄后才能下訂單哦!
如何分析Spring Security中過(guò)濾器鏈的配置問(wèn)題,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
首先這個(gè)問(wèn)題本身是有點(diǎn)問(wèn)題的,因?yàn)?http.authorizeRequests()
并非總是第一個(gè),雖然大部分情況下,我們看到的是第一個(gè),但是也有很多情況 http.authorizeRequests()
不是首先出現(xiàn)。要搞明白這個(gè)問(wèn)題,我們就要搞清楚 http.authorizeRequests()
到底是啥意思!
這就涉及到 Spring Security 中過(guò)濾器鏈的配置問(wèn)題
即使大家沒(méi)有仔細(xì)研究過(guò) Spring Security 中認(rèn)證、授權(quán)功能的實(shí)現(xiàn)機(jī)制,大概也都多多少少聽(tīng)說(shuō)過(guò) Spring Security 這些功能是通過(guò)過(guò)濾器來(lái)實(shí)現(xiàn)的。
是的,沒(méi)錯(cuò)!Spring Security 中一共提供了 32 個(gè)過(guò)濾器,其中默認(rèn)使用的有 15 個(gè),這些過(guò)濾器松哥在以后的文章中再和大家細(xì)說(shuō),今天我們就先來(lái)看看過(guò)濾器的配置問(wèn)題。
在一個(gè) Web 項(xiàng)目中,請(qǐng)求流程大概如下圖所示:
請(qǐng)求從客戶(hù)端發(fā)起(例如瀏覽器),然后穿過(guò)層層 Filter,最終來(lái)到 Servlet 上,被 Servlet 所處理。
那有小伙伴要問(wèn)了,Spring Security 中默認(rèn)的 15 個(gè)過(guò)濾器就是這樣嵌套在 Client 和 Servlet 之間嗎?
不是的!
上圖中的 Filter 我們可以稱(chēng)之為 Web Filter,Spring Security 中的 Filter 我們可以稱(chēng)之為 Security Filter,它們之間的關(guān)系如下圖:
可以看到,Spring Security Filter 并不是直接嵌入到 Web Filter 中的,而是通過(guò) FilterChainProxy 來(lái)統(tǒng)一管理 Spring Security Filter,F(xiàn)ilterChainProxy 本身則通過(guò) Spring 提供的 DelegatingFilterProxy 代理過(guò)濾器嵌入到 Web Filter 之中。
?DelegatingFilterProxy 很多小伙伴應(yīng)該比較熟悉,在 Spring 中手工整合 Spring Session、Shiro 等工具時(shí)都離不開(kāi)它,現(xiàn)在用了 Spring Boot,很多事情 Spring Boot 幫我們做了,所以有時(shí)候會(huì)感覺(jué) DelegatingFilterProxy 的存在感有所降低,實(shí)際上它一直都在。
上面和大家介紹的是單個(gè)過(guò)濾器鏈,實(shí)際上,在 Spring Security 中,可能存在多個(gè)過(guò)濾器鏈。
在松哥前面講 OAuth3 系列的時(shí)候,有涉及到多個(gè)過(guò)濾器鏈,但是一直沒(méi)有拎出來(lái)單獨(dú)講過(guò),今天就來(lái)和大家分享一下。
有人會(huì)問(wèn),下面這種配置是不是就是多個(gè)過(guò)濾器鏈?
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated()
...
.csrf().disable();
}
這樣的配置相信大家都見(jiàn)過(guò),但是這并不是多個(gè)過(guò)濾器鏈,這是一個(gè)過(guò)濾器鏈。因?yàn)椴还苁?/admin/**
還是 /user/**
,走過(guò)的過(guò)濾器都是一樣的,只是不同的路徑判斷條件不一樣而已。
如果系統(tǒng)存在多個(gè)過(guò)濾器鏈,多個(gè)過(guò)濾器鏈會(huì)在 FilterChainProxy 中進(jìn)行劃分,如下圖:
可以看到,當(dāng)請(qǐng)求到達(dá) FilterChainProxy 之后,F(xiàn)ilterChainProxy 會(huì)根據(jù)請(qǐng)求的路徑,將請(qǐng)求轉(zhuǎn)發(fā)到不同的 Spring Security Filters 上面去,不同的 Spring Security Filters 對(duì)應(yīng)了不同的過(guò)濾器,也就是不同的請(qǐng)求將經(jīng)過(guò)不同的過(guò)濾器。
正常情況下,我們配置的都是一個(gè)過(guò)濾器鏈,多個(gè)過(guò)濾器鏈怎么配置呢?松哥給大家一個(gè)舉一個(gè)簡(jiǎn)單的例子:
@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("江南一點(diǎn)雨").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()
開(kāi)始,
http.authorizeRequests()
配置表示該過(guò)濾器鏈過(guò)濾的路徑是
/**
。在靜態(tài)內(nèi)部類(lèi)里邊,我是用了
http.antMatcher("/bar/**")
開(kāi)啟配置,表示將當(dāng)前過(guò)濾器鏈的攔截范圍限定在
/bar/**
。從上面這段代碼中大家可以看到,configure(HttpSecurity http) 方法似乎就是在配置過(guò)濾器鏈?是的沒(méi)錯(cuò)!我們?cè)谠摲椒ㄖ械呐渲?,都是在添?移除/修改 Spring Security 默認(rèn)提供的過(guò)濾器,所以該方法就是在配置 Spring Security 中的過(guò)濾器鏈,至于是怎么配置的,松哥以后抽時(shí)間再來(lái)和大家細(xì)說(shuō)。
最后,我們?cè)诨氐揭婚_(kāi)始小伙伴提的問(wèn)題。
首先,http.authorizeRequests()
配置并非總在第一行出現(xiàn),如果只有一個(gè)過(guò)濾器鏈,他總是在第一行出現(xiàn),表示該過(guò)濾器鏈的攔截規(guī)則是 /**
(請(qǐng)求只有先被過(guò)濾器鏈攔截下來(lái),接下來(lái)才會(huì)進(jìn)入到不同的 Security Filters 中進(jìn)行處理),如果存在多個(gè)過(guò)濾器鏈,就不一定了。
僅僅從字面意思來(lái)理解,authorizeRequests() 方法的返回值是 ExpressionUrlAuthorizationConfigurer.antMatchers("/admin/**").hasRole("admin").antMatchers("/user/**").hasRole("user")
。
看完上述內(nèi)容,你們掌握如何分析Spring Security中過(guò)濾器鏈的配置問(wèn)題的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。