这个类是上面的OncePerRequestFilter的子类,实现了其doInternalFilter方法,所有的业务逻辑在里面实现。这个类也是一个抽象类,但是没有任何的抽象方法,所以只要集成他就可以直接使用了。
这是一个及其重要的类,shiro集成spring的ShiroFilterFactoryBean返回给spring context中的bean就是他,在ShiroFilterFactoryBean类中,getObject方法就是返回给spring context的bean,里面返回的就是AbstractShiroFilter类,具体的实现是org.apache.shiro.spring.web.ShiroFilterFactoryBean.SpringShiroFilter这个类,在构造方法中将SecurityManager和FilterChainResolver类传入到AbstractShiroFilter中。
private static final class SpringShiroFilter extends AbstractShiroFilter {
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
}
在这个类中将filterChainResolver传入进去,filterChainResolver里面有一个属性FilterChainManager,这里面有一个属性filterChains就表示我们在shiroFilterFactoryBean中配置的所有的路径(也可以说是filter的名字)+filter,在filterChainResolver还有一个属性pathMatcher,用来将访问的url和我们匹配的filter的名字像匹配,决定都是调用哪些filter,也就是一个filterChain。
我们再来看一下AbstractShiroFilter中的 doFilterInternal方法
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
throws ServletException, IOException {
Throwable t = null;
try {
final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
final Subject subject = createSubject(request, response);
//noinspection unchecked
subject.execute(new Callable() {
public Object call() throws Exception {
updateSessionLastAccessTime(request, response);
executeChain(request, response, chain);//最后调用的是这个方法,
return null;
}
});
} catch (ExecutionException ex) {
t = ex.getCause();
} catch (Throwable throwable) {
t = throwable;
}
if (t != null) {
if (t instanceof ServletException) {
throw (ServletException) t;
}
if (t instanceof IOException) {
throw (IOException) t;
}
//otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
String msg = "Filtered request failed.";
throw new ServletException(msg, t);
}
}
executeChain方法如下:
protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain)
throws IOException, ServletException {
FilterChain chain = getExecutionChain(request, response, origChain);//调用这个方法获得此次访问应该调用的filter链。
chain.doFilter(request, response);
}
getExecutionChain的代码如下:
protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
FilterChain chain = origChain;
FilterChainResolver resolver = getFilterChainResolver();//他是根据配置的filterChainResolver来获得匹配的filterChain。这里的origChain就是我们在web.xml里面配置的那个DelegatingFilter,就是用来调用shiro的所有请求的代理filter,所有访问shiro的filter都是由它获得。
if (resolver == null) {
log.debug("No FilterChainResolver configured. Returning original FilterChain.");
return origChain;
}
FilterChain resolved = resolver.getChain(request, response, origChain);
if (resolved != null) {
log.trace("Resolved a configured FilterChain for the current request.");
chain = resolved;
} else {
log.trace("No FilterChain configured for the current request. Using the default.");
}
return chain;
}
通过这个方法我们基本就知道了shiro的处理请求的流程,当某个请求来了之后,他是通过调用配置的ChainResolver调用匹配的路径,如果找到了对应的路径就执行配置的路径后面的所有的filter。另外ShiroFilterFactoryBean向spring context中传入的bean不是传入的自身,而是传入的org.apache.shiro.spring.web.ShiroFilterFactoryBean.SpringShiroFilter这个类,传入的类(也就是spring中的ObjectType)是SpringShiroFilter.class;也不是他自身。