目录
WebSecurityConfig
何时调用 configure(WebSecurity)
AbstractConfiguredSecurityBuilder
如何赋值ignoredRequests
紧接上一篇文章,这一篇我们来看看核心过滤器FilterChainProxy的构造参数对象ignoredRequests是如何被赋值的?
点击WebSecurity的performBuild()方法,如下:
@Overrideprotected Filter performBuild() throws Exception {List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(chainSize);for (RequestMatcher ignoredRequest : ignoredRequests) {securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));}for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {securityFilterChains.add(securityFilterChainBuilder.build());}FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);if (httpFirewall != null) {filterChainProxy.setFirewall(httpFirewall);}filterChainProxy.afterPropertiesSet();Filter result = filterChainProxy;postBuildAction.run();return result;}
通过前面的文章,我们知道这里是创建核心过滤器对象的方法。
在这里,我们知道securityFilterChains列表对象是核心过滤器的构造参数,其中,该列表对象有一部分内容是来自于ignoredRequests这个WebSecurity的属性。
通过前面的文章,我们也知道,通过在自定义配置类里重写方法configure(WebSecurity web),可以让WebSecurity对象的ignoredRequests属性有值。
自定义配置如下所示:
WebSecurityConfig
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {... ...
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers("/css/**", "/js/**")
.regexMatchers("/api/public/.*");
}
接下来,我们要探究两个问题:
其一,自定义配置类里的方法configure(WebSecurity web)何时被调用?
其二,自定义配置内容是如何影响到ignoredRequests属性的?
何时调用 configure(WebSecurity)
通过前面的文章,我们知道AbstractConfiguredSecurityBuilder的doBuild()方法,保存了构建核心过滤器的所有步骤。
点击进入,如下所示:
AbstractConfiguredSecurityBuilder
@Override
protected final O doBuild() throws Exception {
synchronized (configurers) {
buildState = BuildState.INITIALIZING;
beforeInit();
init();
buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
buildState = BuildState.BUILDING;
O result = performBuild();
buildState = BuildState.BUILT;
return result;
}
}
在这里,步骤configure看着跟我们要解决的问题关系比较大,点击configure(),如下所示:
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
在这里,果不其然,调用了自定义配置类的configure(WebSecurity)方法,并将当前的WebSecurity对象作为参数传递给配置类方法。
如何赋值ignoredRequests
点击自定义配置类配置内容的web.ignoring(),如下所示:
public WebSecurity.IgnoredRequestConfigurer ignoring() {
return this.ignoredRequestRegistry;
}
在这里,返回WebSecurity建造者的属性ignoredRequestRegistry,该属性类型为WebSecurity建造者的内部类IgnoredRequestConfigurer,该类继承于AbstractRequestMatcherRegistry类。
点击配置类配置内容的.antMatchers("/css/**", "/js/**"),如下所示:
public abstract class AbstractRequestMatcherRegistry<C> {
... ...
public C antMatchers(String... antPatterns) {
return this.chainRequestMatchers(AbstractRequestMatcherRegistry.RequestMatchers.antMatchers(antPatterns));
}
在这里,这是IgnoredRequestConfigurer的父类。
点击RequestMatchers.antMatchers()方法,如下所示:
private static final class RequestMatchers {
public static List<RequestMatcher> antMatchers(HttpMethod httpMethod, String... antPatterns) {
String method = httpMethod == null?null:httpMethod.toString();
List<RequestMatcher> matchers = new ArrayList();
String[] var4 = antPatterns;
int var5 = antPatterns.length;
for(int var6 = 0; var6 < var5; ++var6) {
String pattern = var4[var6];
matchers.add(new AntPathRequestMatcher(pattern, method));
}
return matchers;
}
在这里,这是一个静态方法,将String类型的请求地址串转换为RequestMatcher对象,这个类型也正是ignoredRequests对象的类型。
让我们回到上一步,点击chainRequestMatchers()方法,如下所示:
public class IgnoredRequestConfigurer extends AbstractRequestMatcherRegistry<WebSecurity.IgnoredRequestConfigurer> {
... ...
protected WebSecurity.IgnoredRequestConfigurer chainRequestMatchers(List<RequestMatcher> requestMatchers) {
WebSecurity.this.ignoredRequests.addAll(requestMatchers);
return this;
}
在这里,终于看到ignoredRequests对象了。原来,WebSecurity是通过属性ignoredRequestRegistry的方法来将自定义配置的请求地址串注册到WebSecurity建造者对象。
疏漏之处恭请雅正,良策佳议敬候惠示,凡所赐教必当铭感于心。