上一篇博文主要讲了SpringShiroFilter的初始化过程,这篇文章主要解析SpringShir Filter在处理请求时做了些什么。
SpringShiroFilter处理请求的中心思想是获取某个请求对应的shiroFilterChain,并添加到javaEE规范的FilterChian中,从而使得配置的过滤器能够被调用,具体怎么做到的,我们看正文的解析
首先,还是先给出SpringShiroFilter的继承结构,如下图:
既然是过滤器,那么一定是有一个doFilter方法供Servlet容器调用(如tomcat),,SpringShiroFilter中没有这个方法,我们一层一层的的往上找,直到在OncePerRequestFilter中找到该方法
这里会调用到125行的doFilterInternal()方法,该方法是个抽象方法,那么查看他的子类AbstractShiroFilter。在第356-359行对request和response进行了处理,以及创建了一个Subject。这里本篇文章不讲述其中的过程。后面会出专门的文章讲述。主要涉及到脱离容器的session实现以及Subject的创建。关注到362行,这里匿名实现了一个callable接口,最终调用到365行的excuteChain(),这是整个SpringShiroFilter的核心所在
这里的逻辑是获取一个可执行的过滤链,并调用其doFilter()方法触发下一个过滤器往下执行。getExecutionChain()方法进一步点进去,这里第一步409行获得初始化时注入的FilterChainResolver,第二步415行通过这个解析器获得初始化时配置好的过滤链
点进415行获取过滤链的具体方法,第一步,获取到请求的URI,第二步,将URI与xml中配置的URL进行逐个比对,第三步对这个匹配的过滤器进行代理(这个很重要)并返回
细看第二步,点进比对方法,这里把它委托给了初始化时默认的AntPathMarcher,最终实现比较逻辑的是doMatch方法。(所以我们以后要实现shiro兼容restFul路径时应该要重新的就是这个类的该方法,并注入到FilterChainResolver)
回到第三步,点进111行的proxy()方法
继续点进proxy()方法
这里返回了一个被包装了的FilterChain,看看他的doFilter方法。(注释翻译:如果封装好的chain到了末端,那么开始调用原生的过滤链)。所以这里会将shiro的过滤链先调用完,再执行javaEE规范的过滤链。
现在完成了最重要的一步,将FilterChain进行了代理,下面一路回退,回退到最开始的executerChain()方法,在得到这个代理过滤链后直接调用doFilter方法触发我们配置的具体过滤器。
自此,SpringShiroFilter完成了他的使命--通过组合的方式将shiroFilterChian添加到FilterChian中,所以一旦经过经过了这个过滤器,那么我们的filterChain可就不是原来的filterChain了,shiro通过组合的设计模式对doFilter()方法的具体实现修改了,并且丝毫不影响客户端调用代码,甚至都感知不到原来这个FilterChain已经被shiro"无耻"的篡改了。
本篇文章讲了SpringShiroFilter将ShiroFilterChain加载到FilterChain的实现原理,下一篇文章将以PermissionsAuthorizationFilter为例讲解具体的ShiroFilter过滤的步骤。