shiro Filter加载和执行 源码解析

一、背景

在使用若依框架(前后端不分离包含shiro安全框架)时,发现作者添加了验证码、登录帐号控制等自定义过滤器,于是对自定的过滤器加载和执行流程产生疑问。下面以验证码过滤器为例,对源码解析。注意类之间的继承关系和类中属性存储的值。

二、过滤器加载流程

1、ShiroFilterFactoryBean类创建

(1)、在ShiroConfig中有ShiroFilterFactoryBean 创建及配置类(若依中使用的是CustomShiroFilterFactoryBean,继承了ShiroFilterFactoryBean),其中有两个重要配置,一是filters ,自定义过滤器Map集合,key为拦截器别名,可以配置在FilterChainDefinitionMap中value值,value是过滤器实体,二是FilterChainDefinitionMap ,key为要过滤的url,value是使用的过滤器别名,需要和filters中key值匹配。例如如下图,/login及/register两个url会被验证码过滤器过滤。

2、FilterChainManager类创建

(1)、CustomShiroFilterFactoryBean继承了ShiroFilterFactoryBean实现了FactoryBean类所以spring创建这种类型的类时,会执行getObject如果对象不存在则创建执行createInstance。

(2)、在createInstance 中会执行createFilterChainManager方法创建FilterChainManager ,createFilterChainManager方法中会给FilterChainManager设置两个重要属性,第一个遍历(1.1处配置)filters集合给FilterChainManager中的filters集合赋值,key为filter别名,value为filter实体,此时会给Nameable类型filter设置Name为filter别名。此时FilterChainManager中属性filters中添加了所有自定义过滤器和系统默认的过滤器。系统默认过滤器时在创建对象DefaultFilterChainManager构造方法中调用addDefaultFilters添加,DefaultFilterChainManager继承FilterChainManager。

(3)、获取(上面1.1配置)FilterChainDefinitionMap过滤器链并遍历,在DefaultFilterChainManager中执行createChain创建过滤器执行链。

filterTokens为filter别名数组,遍历数组执行addToChain,第一个参数是url,第二个是filter别名,第三个是filter配置参数。继续跟踪addToChain。

(4)、SimpleNamedFilterList实现了NamedFilterList类,addToChain方法中创建SimpleNamedFilterList类,ensureChain方法把filter放入SimpleNamedFilterList类属性backingList集合中。DefaultFilterChainManager中属性filterChains中存的是以url为key,value是SimpleNamedFilterList类型的对象。

(5)、总结一下,创建DefaultFilterChainManager完成后,DefaultFilterChainManager中有两个重要属性,一个是filters所有过滤器map集合,第二个是filterChains所有url对应过滤器链,例如/login,对应SimpleNamedFilterList类中属性backingList集合中有invaldRequetFilter、AnonymousFiter、CaptchaValidateFilter三个过滤器。

3、MySpringShiroFilter类创建

PathMatchingFilterChainResolver类中setFilterChainManager把2中创建的DefaultFilterChainManager设置到filterChainManager属性中。创建MySpringShiroFilter时,通过构造函数把PathMatchingFilterChainResolver传入。MySpringShiroFilter继承自AbstractShiroFilter,最终给AbstractShiroFilter的属性filterChainResolver赋值。

总结一下,通过shiroConifg类最终创建出的mySpringShiroFilter继承AbstactShiroFilter,AbstactShiroFilter中属性filterChainResolver为pathMatchingFilterChainResolver,AbstactShiroFilter继承了OncePerRequestFilter,所以在过滤url时执行doFilterInternal方法。

4、过滤器执行流程

doFilterInternal中执行executeChain->getExecutionChain

getFilterChainResolver获取PathMatchingFilterChainResolver,执行PathMatchingFilterChainResolver中的getChain

如下图执行步骤,匹配成功后执行DefaultFilterChainManager类中proxy方法。

通过url获取SimpleNamedFilterList类,执行SimpleNamedFilterList类中proxy方法。

创建出ProxiedFilterChain对象,其中第二个参数是SimpleNamedFilterList自身。

最终返回ProxiedFilterChain对象,执行ProxiedFilterChain中doFilter方法,会按顺序执行该url对应的过滤器。

captchaValidateFilter继承关系,执行captchaValidateFilter的doFilter方法

时会进入父类OncePerRequestFilter的doFilterInternal,

进入父类adviceFilter的doFilterInernal,

进入父类PathMatchingFilter中preHandle,配上url后,执行isFilterChainContinued

执行到父类AccessControlFilter的onPreHandle,最终执行到本类CaptchaValidateFilter的onAccessDenied和onAccessDenied方法,有一个满足即为true.

执行完成后,继续返回到adviceFilter.判断是否继续执行下一个filter。


相关推荐
半杯咖啡半行码1 分钟前
C++ 编程与 STL 模板:从泛型编程到内存安全详解
开发语言·c++
小兔子8 分钟前
Python 的 GIL 与 free-threading:3.13 之后「去 GIL」走到哪一步了
前端
十年Java程序媛11 分钟前
Java 接口和抽象类对比|Java8 新特性,抛弃老旧八股,正确选型
java·spring boot·后端
caoerzhong14 分钟前
JeeWMS 开源 WMS 部署避坑指南:Java 仓库管理系统的环境基线、四类根因与可复现交付
java·开发语言·开源
用户37215742613514 分钟前
Java 合并 PDF 文件:完整合并、指定页面合并与流合并
java
IT_陈寒14 分钟前
SpringBoot自动配置差点让我加班到凌晨
前端·人工智能·后端
时间的拾荒人16 分钟前
Qt 界面优化:绘图详解 —— 从基础图形到图片处理
开发语言·qt·面试
MayZork34 分钟前
Qt 文件操作:QSaveFile 与 QTemporaryFile(含 QTemporaryDir)实战
开发语言·qt
北冥you鱼1 小时前
Go 语言空接口(interface{})使用场景与最佳实践
开发语言·windows·golang
for_ever_love__1 小时前
MySQL 全文索引实战:FULLTEXT、ngram 中文分词与 MATCH AGAINST 到底该怎么用
java·python·mysql·全文检索·分词·索引·ngram