在一个实际项目中。并非所有的请求都需要经过过滤器,有一些特殊的请求,比如说静态资源,就不需要经过过滤器链。
经过之前对过滤器链的分析,我们知道在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;
}