servlet的初始化会触发核心过滤器的创建:

public Object getObject() throws Exception {
if (instance == null) {
instance = createInstance();
}
return instance;
}

在createInstance方法中会调用

protected FilterChainManager createFilterChainManager() {

    DefaultFilterChainManager manager = new DefaultFilterChainManager();
Map<String, Filter> defaultFilters = manager.getFilters();
//apply global settings if necessary:
for (Filter filter : defaultFilters.values()) {
applyGlobalPropertiesIfNecessary(filter);
} //Apply the acquired and/or configured filters:
Map<String, Filter> filters = getFilters();
if (!CollectionUtils.isEmpty(filters)) {
for (Map.Entry<String, Filter> entry : filters.entrySet()) {
String name = entry.getKey();
Filter filter = entry.getValue();
applyGlobalPropertiesIfNecessary(filter);
if (filter instanceof Nameable) {
((Nameable) filter).setName(name);
}
//'init' argument is false, since Spring-configured filters should be initialized
//in Spring (i.e. 'init-method=blah') or implement InitializingBean:
manager.addFilter(name, filter, false);
}
} //build up the chains:
Map<String, String> chains = getFilterChainDefinitionMap();
if (!CollectionUtils.isEmpty(chains)) {
for (Map.Entry<String, String> entry : chains.entrySet()) {
String url = entry.getKey();
String chainDefinition = entry.getValue();
manager.createChain(url, chainDefinition);
}
} return manager;
}

DefaultFilterChainManager默认构造器会填充所有默认的filter,为11个。

public DefaultFilterChainManager() {
this.filters = new LinkedHashMap<String, Filter>();
this.filterChains = new LinkedHashMap<String, NamedFilterList>();
addDefaultFilters(false);
} protected void addDefaultFilters(boolean init) {
for (DefaultFilter defaultFilter : DefaultFilter.values()) {
addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
}
}

当你有自己的实现时,如扩展了FormAuthenticationFilter,key为authc,增加了一个check和ssoAuthc。

<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter" />
<entry key="check" value-ref="authcFilter"/>
<entry key="ssoAuthc" value-ref="MyShiroCasFilter"/>
</util:map>
</property>

这时ShiroFilterFactoryBean维护这3个。

createFilterChainManager方法会把默认的给覆盖掉,因为自定义和默认的key均为authc。

public void addFilter(String name, Filter filter, boolean init) {
addFilter(name, filter, init, true);
} protected void addFilter(String name, Filter filter, boolean init, boolean overwrite) {
Filter existing = getFilter(name);
if (existing == null || overwrite) {
if (filter instanceof Nameable) {
((Nameable) filter).setName(name);
}
if (init) {
initFilter(filter);
}
this.filters.put(name, filter);
}
}

操作完后DefaultFilterChainManager维护13个(覆盖1个,新增2个)

然后构造Map

/images/** = anon
/css/** = anon
/resources/** = anon
/js/** = anon
/static/** = anon
/logout.do = anon
/rest/** = anon
/** = check,authc

如上面的map转换成filterChains之后,key为”/**”的value是一个包含两个过滤器的NamedFilterList(一个名叫check 一个名为authc)。

当请求过来时,PathMatchingFilterChainResolver的getChain来获取需要的过滤器链,这个会匹配之前保存的Map集合,匹配上就立马返回这个代理的过滤器链(ProxiedFilterChain)。

然后就是执行代理过滤器链:

整个过程就是先解析配置文件中的映射关系,转化成内存中的Map映射,当一个请求过来时, 先被核心过滤器拦截,然后根据匹配规则构造代理过滤器链,这个代理过滤器链包含了需要走的过滤器。

最后执行代理过滤器链的doFilter方法:遍历需要执行的匹配上的过滤器,挨个执行,但是自定义和默认的过滤器都是传的ProxiedFilterChain本身,所以放行的时候又会绕回ProxiedFilterChain的doFilter方法,这样就形成了逻辑上的链,shiro自己的链式执行。

匹配的过滤器执行完后,才会放行到servlet的过滤器链继续执行。

05-25 22:00