记录升级Shiro版本后,出现的一些问题
项目原本使用的Shiro是1.3.0版本的,而shiro官方发布了Apache Shiro权限绕过漏洞(CVE-2020-17523)风险通告。使用shiro和spring的用户都需升级到最新的shiro-1.7.1版本。
于是在pom.xml中修改了版本号之后重新发布了项目,并进行了测试。测试中发现了一些因升级shiro版本出现的问题,在此记录。
URL中存在中文的请求被拦截
测试接口时发现,原来的部分接口会将中文参数拼接在URL路径上,如/hello/你好,这种请求方式在低版本shiro没有问题,而升级后却出现请求被拦截了。
后经过查阅资料与阅读源码后发现,1.7.1版本的ShiroFilterFactoryBean
的 globalFilters
中默认加载了一个InvalidRequestFilter
.
该Filter
的第三次校验中,调用的request.getPathInfo()
会将原本编码过的url重新解码,isValid()负责校验url是否存在非Ascii编码的字符,所以就是在这里请求被拦截了。
解决方式
- 如果存在较少的URL不规范的话,还是建议修改URL,将中文以参数的格式发送,如/hello?key=你好。
- 如果不想大范围的排查URL规范,可以修改这个
ShiroFilterFactoryBean
,将InvalidRequestFilter
移除。下面贴出我的实现。
重定向次数过多
部分用户反应一些接口出现重定向次数过多报错。
经过排查,发现了一个重定向的请求中Response Headers中的一个响应头Set-Cookie的值里面有SameSite=lax
这个属性。该属性是浏览器用来防止CSRF攻击的,当使用第三方cookie时,该属性的值会决定是否允许发送cookie,详情见:www.ruanyifeng.com/blog/2019/0… 。
而系统中的单点登入是接的第三方的,登录后会返回一个cookie,而我们的系统在请求时会携带这个cookie,表示用户已经登录成功了。
但我们的系统和第三方的系统不在一个网段,请求存在跨域,而单点登录的cookie对我们系统来说成了第三方cookie,被浏览器禁止发送了。
然后就变成:请求后台接口(未携带cookie)-> 判断是否登入 -> 未登录,重定向到登录系统(这时会记录跳转来时的接口,以便登录后再跳回去) -> 判断是否登入(由于登陆系统就是第三方的,所以这次会携带cookie) -> 已登录 -> 跳转到请求的接口(未携带cookie)--> 后面就死循环了,直到报错。
哪里设置了SameSite?
通过查看代码发现系统使用了org.apache.shiro.web.servlet.SimpleCookie
来设置cookie。这里默认为san'me
解决方式
- 将请求换成https请求,并将
SameSite
值设为none。(没试过) - 将这个默认的值设为null。
本人采用的方式的并不好,从某种程度上会降低系统的安全,如果有更好的方式希望能够分享给我。