前言
shiro是apche的一个开源权限框架,本人学习的同时准备记录一下阅读源码的过程,出一个关于shiro的源码解析系列文章,其中主要包括过滤器,Subject的创建与维护,Session的管理,登录授权的流程,缓存管理。同时熟悉这些之后再基于shiro来进行改造以适应于restful以及jwtToken的技术方案
谁适合读本篇文章
如果您从未使用过shiro,那么本篇文章可能不适合您(shiro使用教程友情跳转:shiro.apache.org/documentati…),本文假设读者已经掌握了shiro的基本使用,并想进一步探索shiro的原理。
本文的内容总览
本篇为该系列的第一章,解析shiro过滤器的实现原理,主要分为两个部分,第一部分解析spring启动时shiro过滤器的初始化过程,第二部分解析前端发起一个请求后端过滤器权限验证的流程。由于篇幅过长,本文仅讲解第一部分:Filter的初始化过程。第二部分Filter的过滤流程见下一篇博文
Filter的初始化
这个部分宏观上来讲,只做了一个工作,就是构建了ShiroFilter。首先给出shiroFilter的配置文件spring-shiro.xml
1、首先根据spring-shiro.xml的配置作为入口,看看这个Filter是如何构建出来的。(本文的示例工程代码地址: github.com/liuruojing/…) 2、这是一个Filter工厂类,所以找到他创建实例的方法。同时需要注意一下他的成员变量,filters是自定义的过滤器,filterChainDefinitionMap是过滤链的配置,loginUrl是登录地址,这些都是在spring-shiro.xml中配置的 注:174行开始创建过滤链管理器3、点击方法,看看是如何创建这个过滤链管理器的,主要包含三步:
1、添加默认的过滤器
2、添加自定义的过滤器
3、构建过滤链
回到第3步的371行,这里为每个filter设置了一些我们配置的参数
回到第3步的376-389行,将我们自定义的拦截器初始化配置并添加到DefaultFilterChainManager中,至此,我们的所有过滤器们(包括默认的以及我们自定义的)已经全部初始化完了,都存在DefaultFilterChainManager中。
4、继续看392行,现在开始初始化FilterChains(构建过滤链) 这里392行获取我们所配置的权限列表,例如(/user/**=authc,perms[user:add,user:delete],这里等号左边表路径,perms是拦截器名称,user:add是需要的权限),这里开始遍历map,解析每条配置
点进397行createChain(url,"authc,perms[user:add,user:delete]")方法,在第140行首先对authc,perms[user:add,user:delete]进行切分,切分后结果为string[0]=authc,string[1]=perms[user:add,user:delete],然后在144行对切分后的字符串循环遍历进行操作,以perms[user:add,user:delete]为例。145行返回string[0]=perms,string[1]=user:add,user:delete。最后调用148行添加过滤链,chainName=url,nameConfigPair[0]为过滤器名,nameConfigPair[1]为过滤器针对这个url的配置
点进148行的addToChain方法,方法中263行得到对应的过滤器,270行将配置加到filter里,这里就是对user:add,user:delete解析的过程 过滤器配置完后,272行确认一下是否有对应的过滤器链表,没有的话新建一个,然后将新的过滤器添加到链表尾部 一步一步的解析完所有的权限配置后,最终如filterChains数据结构,这里debug看到结果,最终渲染成如下的数据结构 画出对应的数据结构图如下 那么假如现在有个请求访问/user/add,调用filterChainManager.getchain("urlName")就会返回一个匹配的NamedFilterList过滤链。6、可以看到,这样就建立了url与过滤器之间的关联。既然url已经与过滤链进行了关联,那么我们在处理时只需要将请求的url与我们配置的url进行一个逐条比对,就可以获取到这个过滤链了。可见我们还需要一个PathMacher(路径比对器),现在回到第2步中的175-176行,这里他为我们new了一个PathMatchingFilterChainResolver,看看这个类,构造方法里面就有了一个默认的AntMathMatcher(这是一个ant风格的路径匹配器),并把filterChainManager注入到了里面,对上层调用者提供了一层封装,调用者只需要调永chainResolver.getChain(request)就可以获取到这个请求对应的过滤链了。
最后,将这个filterChainResolver注入到Filter中,完成了Filter的构建。下面给出四个主要类的具体类图
自此,shiroFilter已经初始化完毕,这个初始化过程中主要是构建了一个过滤链,提供了一个getChain()方法来获得过滤链。第二部分将讲解某一个请求后端过滤器权限验证的流程,具体解析获取过滤链,如何执行过滤链,以及自定义过滤器被调用的过滤方法等等