shiro过滤器失效问题研究

问题背景

项目使用了shiro 过滤器拦截请求,做一些限流,鉴权,白名单限制的事情,可是最近在上线一个新功能时,新增了一个拦截路径,上线后,发现部分设置了拦截的路径失效,导致项目回滚

问题定位

之前在本地开发环境出现过类似问题,怀疑是正则表达式覆盖或者是拦截器排序规则导致,可是查了一堆网上资料,均没有类似情况,加之是本地环境问题,也就草草了之了。今天在线上环境碰到就不得不去查明原因,彻底解决。

这也告诉我们问题无大小,遇到问题后就要想办法根治,否则说不定在哪里就有一个坑等着你 。

经过之前的排查,排除正则表达式路径覆盖的怀疑,那么就剩下拦截器排序算法了。下面贴一下我们出问题前的源码配置。
shiro过滤器失效问题研究_第1张图片
出问题时候源码配置
shiro过滤器失效问题研究_第2张图片
观察因顺序原因可能影响到的配置只有“/**”路径的设置,去除后所有拦截生效。

问题原因

通过阅读相关源码,PathMatchingFilterChainResolver引起了我的注意。
shiro过滤器失效问题研究_第3张图片
该代码就是取请求路径,和配置的过滤器路径做正则匹配。通过调试发现此文讨论问题出现前后,filterChainManager.getChainNames()返回的过滤器配置路径顺序是不一致的。写了个测试例子验证下,输出如下
shiro过滤器失效问题研究_第4张图片shiro过滤器失效问题研究_第5张图片
就是因为/**的顺序调整了,所以导致之后的shiro配置都失效了。

filterChainManager.getChainNames()返回的为hashMap的keyset对应的set类型,其遍历的是hashmap的node节点并返回,没有做任何排序,其顺序是hashmap在put时候通过key值的hashcode经过运算得到(hashmap的key是无顺序的)。

在观察一下出问题前后路径的个数,是12个到13个的时候,这个不是偶然的,因为hashmap默认初始化的是16个容量,负载因子是0.75,在12个后所有key会rehash,正是因为rehash导致输出的顺序发生改变,导致类本次悲剧的再发送。

你可能感兴趣的:(腾讯王卡技术之坑记录)