shiro多项目跳转用户身份失效问题排查
1. 身份失效问题
最近在项目中遇到过一个问题,统一登录系统中有各个子系统的模块,可点击子系统模块进行跳转,如下图所示:
如上图,当用户点击子系统B
新窗口打开时,实现跳转成功,当再回到原统一登录系统页面,再点击子系统A
或者子系统B
,却报出用户失效
类似的问题。
2. 问题原因分析
经过浏览器F12
排查接口请求头,发现一个问题,由于我们这次部署的多个项目,对外都同属一个外网ip下,对于前端来说F12
中的Application
中存储的cookie
名,都为JESSIONID
,为shiro默认的cookie
名。
显然是JESSIONID
值被顶替了,如下图:
下图是具体的前端浏览器在操作时的截图操作:
如上图,初次访问时,已经有一个JESSIONID
,对应的值为这个。如果后端不对cookie名进行设置,默认都会为JESSIONID
。当系统正常使用,每一个请求都会在request_header
里携带cookie
值,传递给后台,后台通过设置的cookie
名,即JESSIONID
里取出cookie
,验证session
身份。
当多个项目在同一个域下(前端对外访问只要在同一个ip下,都算作一个域),如果不进行设置,统一登录登录成功后,本来有自己的JESSIONID
,当跳转子系统,恰巧子系统和统一登录同属一个域,并且子系统也是默认的JESSIONID
值,就会用子系统的JESSIONID
值冲掉前者的JESSIONID
值,导致切换回统一登录点击另一个子系统时,会显示身份失效等问题。
统一登录再次操作时,会使用子系统新的JESSIONID
值发起请求,到统一登录服务,此时拿着子系统的钥匙去统一登录找身份,肯定失败。
当然发生这种情况的时候,前提是统一登录和子系统访问地址同处一个ip下
,如果不是这种情况,一般没有这个问题,但是实际部署的时候,发生这种情况还是很多的。
3. 问题解决办法
问题找到了,解决办法就好找了,就是对统一登录和子系统的对应的cookie名,各自起一个,让它们不再冲突即可。
对于shiro
框架里,可以对cookie名进行设置,如下图所示,对应的SimpleCookie simpleCookie = new SimpleCookie("ynzl_cookie")
,这里起名为ynzl_cookie
即可。
@Bean(name = {"sessionIdCookie"})
public SimpleCookie getSessionIdCookie() {
//sessionid名称,每个系统都必须不一致
SimpleCookie simpleCookie = new SimpleCookie("ynzl_cookie");
simpleCookie.setMaxAge(-1);
simpleCookie.setHttpOnly(true);
return simpleCookie;
}
总之,用户失效的问题,基本有以下几种原因:
- 用户身份压根在第一次登录时,就没存储成功,锁都没了,钥匙再对也白搭了。
- cookie被重置了,就像本文的问题一样,钥匙被替换了,拧断手也是开不开的。
- 时效性,
cookie
和session
的时间配置,也应该保证一定时间可用,如果太短,很容易就失效了。