在一個實際項目中。並非所有的請求都需要經過過濾器,有一些特殊的請求,比如說靜態資源,就不需要經過過濾器鏈。
經過之前對過濾器鏈的分析,我們知道在WebSecurity中維護了一個ignoredRequests變量,記錄了所有需要被忽略的請求
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
public void configure(WebSecurity web) throws Exception{
web.ignoring().antMatchers("/login.html","/css/\*\*","/js/\*\*","/images/\*\*");
}
@Override
public void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf().disable();
}
}
重寫configure(WebSecurity web)方法,配置需要忽略的請求,這些請求都會被添加到ignoredRequests集合中,最終以過濾器鏈的形式存在。也就是說,上面的配置一共有5個過濾器鏈,configure(WebSecurity web)配置的4個和configure(HttpSecurity http)配置的1個(/**)。
我們可以看下WebSecurity的源碼
/**
* 各種配置信息已經搜集齊備,通過該方法執行構建過程,構建 Filter FilterChainProxy 實例並返回該 Filter
**/
@Override
protected Filter performBuild() throws Exception {
Assert.state(
!securityFilterChainBuilders.isEmpty(),
"At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
+ "Typically this done by adding a @Configuration that extends "
+ " WebSecurityConfigurerAdapter."
+ " More advanced users can invoke " + WebSecurity.class.getSimpleName()
+ ".addSecurityFilterChainBuilder directly");
// 計算出要創建的過濾器鏈 SecurityFilterChain 的個數 :
// ignoredRequests 中URL通配符的個數 + securityFilterChainBuilders元素的個數,
// 這里每個 securityFilterChainBuilders 元素實際上是一個 HttpSecurity
int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(
chainSize);
// 對於每個要忽略的URL通配符,構建一個 SecurityFilterChain 實例,使用的實現類為
// DefaultSecurityFilterChain , 該實現類實例初始化時不包含任何過濾器,從而對給定的URL,
// 可以達到不對其進行安全檢查的目的
for (RequestMatcher ignoredRequest : ignoredRequests) {
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
}
// 對每個 securityFilterChainBuilder 執行其構建過程,生成一個 securityFilterChain,
// 這里每個 securityFilterChainBuilders 元素實際上是一個 HttpSecurity
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder :
securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());
}
// 由多個 SecurityFilterChain securityFilterChains 構造一個 FilterChainProxy,這就是最終要構建的
// Filter : FilterChainProxy : springSecurityFilterChain
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (httpFirewall != null) {
filterChainProxy.setFirewall(httpFirewall);
}
// 對根據配置新建的 filterChainProxy 進行驗證,
// FilterChainProxy 的缺省驗證器是一個 NullFilterChainValidator,相應的驗證邏輯為空方法
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
if (debugEnabled) {
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);
}
postBuildAction.run();
return result;
}