框架介紹
Spring Security是Spring全家桶的成員,官方對它的介紹是:
Spring Security 是一個功能強(qiáng)大且高度可定制的身份驗(yàn)證和訪問控制框架。
它是保護(hù)基于 Spring 的應(yīng)用程序的事實(shí)標(biāo)準(zhǔn)。
Spring Security 是一個專注于為 Java 應(yīng)用程序提供身份驗(yàn)證和授權(quán)的框架。
與所有 Spring 項(xiàng)目一樣,Spring Security 的真正強(qiáng)大之處在于它可以輕松擴(kuò)展以滿足自定義需求。
從介紹里可以看出,Spring Security是一個可定制擴(kuò)展的框架,它主要提供了身份驗(yàn)證和訪問控制功能。而這兩個功能也是基于框架的擴(kuò)展機(jī)制開發(fā)的,下面讓我們一起了解一下Spring Security的基本概念和擴(kuò)展機(jī)制的實(shí)現(xiàn)原理。
基本概念
要了解Spring Security內(nèi)部的運(yùn)行機(jī)制,要先了解它包含的基本概念,以及對應(yīng)的功能。下面是Spring Security主要的概念:
- 安全過濾器:Spring Security通過向Servlet注冊一個Filter來攔截請求,所以Spring Security要提供自己的過濾器。
- 安全過濾器配置類:為安全過濾器提供統(tǒng)一的配置管理,配置類是
WebSecurity。 - 過濾器鏈:過濾器鏈?zhǔn)菫榱酥С謶?yīng)用在不同業(yè)務(wù)場景有不同的安全規(guī)則需求。一個應(yīng)用可以注冊多個過濾器鏈,一個過濾器鏈包含多個過濾器,一個請求會經(jīng)過所有的過濾器鏈。
- 過濾器鏈配置類:為過濾器鏈提供統(tǒng)一的配置管理,并支持DSL的方式來描述配置,配置類是
HttpSecurity。 - 業(yè)務(wù)過濾器:業(yè)務(wù)過濾器會注冊到過濾器鏈,實(shí)現(xiàn)功能的插拔。
- 業(yè)務(wù)過濾器配置類:用來初始化和注冊業(yè)務(wù)過濾器,也可直接注冊業(yè)務(wù)過濾器。
- 認(rèn)證:是指驗(yàn)證用戶的身份是否合法。Spring Security 提供了多種認(rèn)證方式,如基于用戶名和密碼的認(rèn)證、基于證書的認(rèn)證、LDAP 認(rèn)證、OpenID 認(rèn)證等。
- 授權(quán):是指根據(jù)用戶的身份和角色,決定其是否有權(quán)訪問應(yīng)用程序的資源。Spring Security 支持基于角色的授權(quán)、基于表達(dá)式的授權(quán)等多種授權(quán)方式。
擴(kuò)展原理
Spring Security的功能是基于Filter來實(shí)現(xiàn),當(dāng)一個請求進(jìn)來,會通過全局的安全過濾器判斷,當(dāng)前請求Spring Security是否需要攔截。如果需要攔截,那么請求會流入過濾器鏈,交給過濾鏈的過濾器來處理。
業(yè)務(wù)過濾器可以選擇跳過請求、執(zhí)行操作、結(jié)束請求、將請求交給下一個過濾器。不同的過濾器就實(shí)現(xiàn)了不同的功能,我們以認(rèn)證功能為例,簡單介紹它們的實(shí)現(xiàn)原理。
Spring Security默認(rèn)提供了基于用戶名和密碼的認(rèn)證的功能,實(shí)現(xiàn)這個功能的Filter是UsernamePasswordAuthenticationFilter,從名字就可以看出它的功能。Spring Security會判斷當(dāng)前請求是不是登錄的請求,是的話UsernamePasswordAuthenticationFilter會在請求體里拿到用戶名和密碼,走一遍校驗(yàn)的流程,得到一個Authentication 對象來記錄用戶名和認(rèn)證結(jié)果,并且會把信息存到安全上下文里。
后面訪問其它接口時(shí),校驗(yàn)權(quán)限的Filter里判斷當(dāng)前Authentication 對象能否訪問資源。如果沒有權(quán)限,就會拋出AccessDeniedException 異常。異常處理的Filter會處理Spring Security拋出的異常,給用戶合適的反饋。
所以,Spring Security的認(rèn)證功能是通過認(rèn)證(AuthenticationFilter)、授權(quán)(AuthorizationFilter)、異常處理(ExceptionTranslationFilter)三個Filter配合實(shí)現(xiàn)。通過組合不同的Filter,還能實(shí)現(xiàn)session管理、CSRF攔截等功能。
框架包含的功能
Spring Security框架默認(rèn)提供了一些Filter,來實(shí)現(xiàn)對應(yīng)用程序的安全保護(hù)。下面簡單介紹一下各個Filter的功能:
- DisableEncodeUrlFilter:禁止對URL進(jìn)行編碼,為了禁止在URL里包含session id。在某些無法使用cookie的情況,會將session id放在URL里。
- WebAsyncManagerIntegrationFilter:提供異步請求的支持。
- SecurityContextHolderFilter:獲取安全上下文。
- HeaderWriterFilter:在響應(yīng)頭上加些安全的頭標(biāo)識。
- CsrfFilter:提供CSRF保護(hù)。
- LogoutFilter:提供認(rèn)證登出邏輯。
- UsernamePasswordAuthenticationFilter:提供基于用戶名和密碼的認(rèn)證方式。
- DefaultLoginPageGeneratingFilter:生成默認(rèn)登錄頁。
- DefaultLogoutPageGeneratingFilter:生成默認(rèn)登出頁。
- BasicAuthenticationFilter:提供基于Basic的認(rèn)證方式。
- RequestCacheAwareFilter:提供請求緩存功能,用戶請求出發(fā)登錄認(rèn)證,在認(rèn)證成功之后,繼續(xù)處理之前的請求,所以要保存之前請求的數(shù)據(jù)。
- SecurityContextHolderAwareRequestFilter:通過Spring Security實(shí)現(xiàn)HttpServletRequest里Servlet3.0新增的authenticate()、login()、logout()這些方法。
- AnonymousAuthenticationFilter:提供匿名請求的處理邏輯。
- ExceptionTranslationFilter:提供異常處理邏輯。
- AuthorizationFilter:提供授權(quán)相關(guān)的邏輯。
安全配置
Spring Security允許用戶為框架提供配置信息,來定制安全策略。一般情況,我們只需關(guān)注兩個配置對象:
- WebSecurity
- HttpSecurity
Spring Security6.0版本在配置方式上做了很大改動,支持用戶通過提供Bean來設(shè)置配置,刪除了基于WebSecurityConfigurerAdapter的配置方式。
WebSecurity
WebSecurity用來配置安全過濾器,配置對所有請求都生效。Spring Security6.0推薦的配置方式是注冊一個WebSecurityCustomizer的Bean。
@Configuration
public class SecurityConfiguration {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
}
}
下面這種方式已經(jīng)失效!下面這種方式已經(jīng)失效!下面這種方式已經(jīng)失效!
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/ignore1", "/ignore2");
}
}
HttpSecurity
HttpSecurity用來配置過濾鏈,配置對當(dāng)前過濾鏈里的請求生效。Spring Security6.0推薦的配置方式是注冊一個SecurityFilterChain的Bean。
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
}
下面這種方式已經(jīng)失效!下面這種方式已經(jīng)失效!下面這種方式已經(jīng)失效!
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
}
}
總結(jié)
我們介紹了Spring Security的基本概念和常見功能,分析了Spring Security擴(kuò)展機(jī)制的實(shí)現(xiàn)原理,最后對比了Spring Security6.0的一些改動。可見,使用Spring Security我們通過提供自己的業(yè)務(wù)過濾器,很容易實(shí)現(xiàn)功能的擴(kuò)展。