常用的过滤器为AuthenticatingFilter,具体看一看它是怎么实现的。
先说一下servlet的过滤器链的规则:
servlet中过滤器Filter只有三个方法,当我们自定义过滤器的时候需要实现:
主要就是doFilter方法,他的实现方式是这样子的:
public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException, ServletException {
System.out.println("----调用service之前执行一段代码----");
// 执行目标资源,放行
filterChain.doFilter(request, response);
System.out.println("----调用service之后执行一段代码----");
}
filterChain.doFilter(request, response); 如果这个过滤器链中还有过滤器的话,继续执行下一个过滤器,没有的话,就直接放行,执行请求。
再回过头看一下我们的shiro过滤器实现:
AbstractFilter仅仅实现了Filter接口,没干什么事。
它下面的NameableFilter也没干啥事,就是给filter起了个名字
继续往下走:OncePerRequestFilter保证每个request请求仅经过过滤器一次
每次经过一个过滤器,先设置Attribute,表示该过滤器已经走过了,然后继续执行过滤器的操作,他把过滤器应该执行的操作封装到doFilterInternal()方法中了。
这里的doFilterInternal()方法仅仅是一个抽象方法,还没有实现。
AdviceFilter支持spring的AOP风格,它提供了三个方法preHandle(),postHandle(),afterCompletion()类似于spring中的AOP。这个过滤器也实现了doFilterInternal()方法
先看一下executeChain()方法,这个方法体内是这样的
过滤器链继续往下执行。那么executeChain()方法之前的preHandle()方法就是过滤器方法必须执行的方法,如果该方法返回false,过滤器链就不会继续往下执行。如果过滤器放行请求的话,这个preHandle()必须要返回true。afterCompletion()方法在cleanup()中。接下来看PathMatchingFilter,它的作用主要是匹配当前请求的路径和项目中的路径是否能够匹配,如果能够匹配上,就直接返回isFilterChainContinued()方法,那么isFilterChainContinued()的返回结果,便决定了过滤器是否放行请求。
进入isFilterChainContinued()
从这个日志可以看出,如果请求的路径存在配置中,就执行onPreHandle()方法,从上面可以分析出,如果路径匹配成功,并且onPreHandle()方法返回为True,过滤器放行。
继续分析AccessControlFilter,路径没问题的话,主要看onPreHandle()的返回值即可,onPreHandle()返回为True,过滤器就放行。
可以看出,只要两个方法有一个返回为true,过滤器就会放行。这两个方法在这里都是抽象方法,并未实现。我们继续看这个类的继承类AuthenticationFilter。
这里实现了isAccessAllowed()方法
如果,用户已经登录了,返回true;否则就返回false,进入onAccessDenied()方法。它这里也没有实现onAccessDenied()方法。
再看AuthenticatingFilter,这个类也是一个抽象类onAccessDenied()方法,并未实现,这里面重写了isAccessAllowed()方法,不过调用了父类的isAccessAllowed(),也就是上面一张图的方法。
如果要实现自己的业务的话,就直接继承AuthenticatingFilter就可以了,根据自己的业务逻辑要不要放行,实现一下onAccessDenied()方法就好了。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
总结一下自定义过滤器的执行步骤,可以直接继承AuthenticatingFilter,实现onAccessDenied()方法。如果isAccessAllowed()和onAccessDenied(),两者有一个返回为true,那么过滤器就可以放行(路径正确的话)。
最后,总结的地方如果有什么疏漏之处,欢迎指正。