shiro过滤器详解分析
目录
shiro最核心的2个操作,一个是登录的实现,一就是过滤器了。(认证跟授权是最核心的功能)这里分析下shiro过滤器怎样玩的。
1,目标
这里会按如下顺序逐一看其实原理,并尽量找出其出处。
先看一下shiro过滤器有哪些及它们的别名分别对应哪些类: 点这里.
这里只分析平时用的最多的一个:authc过滤器,对应的处理器的类是FormAuthenticationFilter。
2、继承关系及结构
authc: 1.AbstractFilter > 2.NameableFilter > 3.OncePerRequestFilter > 4.AdviceFilter > 5.PathMatchingFilter > 6.AccessControlFilter > 7.AuthenticationFilter > 8.AuthenticatingFilter > 9.FormAuthenticationFilter
根据这个结构关系可以清楚的知道,接下来要分析的FormAuthenticationFilter上面还有8个。
3、Filter过滤器简介
tomcat中的自定义过滤器必需实现Filter接口,过滤器的实现方法为Filter中的
doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
如果一个请求被该过滤器拦截,想要到达用户最后请求的地址,那么一定得有:filterChain.doFilter(request, response);这个方法的调用,表示通过过滤,请求可以到达用户的请求地址。否则用户的请求地址不会被调用,用户的请求被过滤器拦截。
4、shiro过滤器分析
1、AbstractFilter
位于shiro过滤器最顶层,是个抽象方法,直接继承了Filter,
它只做了一些其本的初始化操作,并没有实现Filter中的doFilter方法。
总结:AbstractFilter只做了一些基本的初始化,并没有过多的逻辑在里面。
2、NameableFilter
允许通过getName和setName方式给过滤器命名。如果没有给该过滤器命名,那么默认将会使用web.xml中给定的名称(FilterConfiger的filterName)
该类可以理解为为过滤器命名用的,也没有实现Filter中的doFilter方法。
总结:NameableFilter是用于给过滤器命名使用的。
3、OncePerRequestFilter
filter的基类(说白了,就是正真实现了Filter中的doFilter方法的类),它用来保证在每个servlet容器上,第个请求都只会被过滤一次,不会重复过滤。
通过getAlreadyFilteredAttributeName()方法来鉴别请求是否已经被过滤过。默认的实现基于具体过滤的实例名称。
接下来看看具体逻辑:
- 判断过滤器是否已经执行过,如果执行过,调用filterChain.doFilter(request, response)直接放行,不再重复执行该过滤器的处理逻辑,直接走下一个过滤器或者通过该过滤进入到实际请求方法中。
- 判断过滤器是否开启,该类有个成员变量eabled,默认为true(注释给的解释是大多数的过滤器都是希望开启的,所以默认值为true),过滤器为开启状态,如果该过滤器没有被开启中,也同上面的逻辑一样,直接走下一个过滤器或者通过该过滤进入到实际请求方法中。
- 这里又分3步,
1、 设置一个已经执行过滤器的属性名称在request中。
2、 调用doFilterInternal方法,执行真正的过滤器处理逻辑。
3、 这个过滤器处理完后,将过滤器的属性名称从request中移出。这样如果程序执行到第2步,过滤又被调用了,它将会走到第一个if中,直接略过这个过滤器的处理,这样就保证了,每个过滤器在处理一个请求的时候只会被执行一次。
总结:OncePerRequestFilter提供了一个实际处理过滤业务的方法doFilterInternal,并且保证每个请求只会被该过滤器过滤一次。
4、AdviceFilter
这个过滤器,类似于开启了AOP环绕通知,提供了preHandle,postHandle和afterCompletion这三个方法。
其过滤逻辑为:doFilterInternal方法。
executeChain方法中的实现为:chain.doFilter(request, response);
所以如果preHandle方法返回false,则说明过滤器不会执行chain.doFilter,意味着请求被拦截掉了,不会进入到用户请求的地址上去。如果为true,表示过滤器放行了过滤的逻辑通过。
然后会执行postHandle方法(该类中的postHandle方法为空实现),
最后会执行一个,这个方法用于对一些异常进行处理(目前也是空实现)。
通过以上可以看出,过滤的逻辑代码实际上是在preHandle这个方法中处理的,这个方法的返回值true和false决定了请求放行和请求被拦截。
总结:AdviceFilter提供了类似于AOP环绕通知式的编程方式,其处理拦截的逻辑是在preHandle方法中完成的。preHandle方法返回true和false代表了通过过滤,请求可以到达用户的请求地址和过滤器拦截掉了用户的请求。
不完整,继续更新中。
博客引用地址.