前言
由于前段时间,我们的服务器被阿里云检测到现在使用的shiro版本有漏洞,项目经理让提高版本。遂把shiro的版本改为了1.8.0,改完之后,竟然发现,项目中配置的登录拦截路径不生效了,任何请求都可以通过。我一度以为这是shiro 1.8版本的一个漏洞。但是作为程序员的我,需要找到到底是什么原因,哪里他们哪里出现了bug(说不定还可以给官方提供建议,手动狗头)。于是,我开始研究shiro底层代码。
查找问题
我们都知道,shiro的只要配置了过滤规则都会通过PathMatchingFilter这个类来校验请求的路径是否与配置的过滤规则匹配。
image.png 也就是通过这个类中的preHandle方法来拦截请求,并与拦截规则进行匹配。那么既然是任何请求都能通过,说明是匹配规则这里出现了问题,我们直接看this.pathsMatch(path, request)这个方法
image.png 再往里面点,发现1.6.0和1.8.0的这个方法中确实有点不太一样:
这是1.6.0版本的pathsMatch的方法:
1.png 这是1.8.0版本的pathsMatch的方法:
2.png
大家发现问题了吧?
1.6.0中,转换过滤规则url时用的是:
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
而1.8.0中,用的是:
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, false, true);
多了两个参数,我们点进去看这个方法的参数:
image.png 可以看到,第三个参数其实是将字符串的前后空格去掉的参数,1.6.0其实是true,也就是去掉前后空格,而1.8.0传的是false,所以没有去掉空格,这就导致在下面的匹配时,将“**+空格” 当成了路径处理:
3.png 所以返回的是false,没有匹配上,所以相当于是校验通过了。
我们再看看如果去掉空格,会是什么情况:
4.png 可以看到,直接运行到方法最后,返回true,相当于是匹配上了,校验没通过,所以将该请求拦截了。
到这里我总算是明白了,原来是我们配置的拦截规则有问题,我看了看配置文件,果然,每个路径后面都有空格:
image.png 把空格去掉,重启,发送请求:
image.png ok,完美!
总结
一开始出现问题时,确实是认为官方的jar包有问题,仔细阅读底层代码配合debug调试,才发现问题的所在,所以养成一个良好的阅读代码的习惯是查找问题的重要手段。