昨天晚上想解决一个springboot应用中session失效的问题,源于公司生产环境目前是一台服务器部署两个
tomcat,应用通过同一个ip访问的时候session会互相冲突。我在网上找了几个解决方案,要么是在tomcat
中conf/context.xml
中Context元素上添加一个sessionCookieName属性,要么是在springboot
server配置上添加servlet.sesssion.cookie.name属性,但是这两个我修改后都不见效,最后还把tomcat源码
下载了下来,看它里面的代码是这么写的
private static String getConfiguredSessionCookieName(Context context) {
// Priority is:
// 1. Cookie name defined in context
// 2. Cookie name configured for app
// 3. Default defined by spec
if (context != null) {
String cookieName = context.getSessionCookieName();
if (cookieName != null && cookieName.length() > 0) {
return cookieName;
}
SessionCookieConfig scc =
context.getServletContext().getSessionCookieConfig();
cookieName = scc.getName();
if (cookieName != null && cookieName.length() > 0) {
return cookieName;
}
}
return null;
}
先从context获取sessionCookieName,如果没有那么再从应用的servletContext中获取sessionCookieConfig,看来我们的思路貌似是
没问题的,但是为什么就不生效呢?在浏览器里看cookieName还是JSESSIONID
, 一时半会找不到答案。但是想想解决思路应该是没问题的,最终目的要把cookie名称给修改掉。
今早醒来突然想到我们的springboot应用里是根据shiro框架来实现权限和会话管理的,会不会跟这个有关系呢?脑子里突然想到这个应该是个
正确的解决方向,于是乎爬起来看了下工程代码,不看不知道,一看就知道应该就是这边的问题,我们看到shiro框架里的DefaultWebSessionManager
是这么写的:
public DefaultWebSessionManager() {
Cookie cookie = new SimpleCookie("JSESSIONID");
cookie.setHttpOnly(true);
this.sessionIdCookie = cookie;
this.sessionIdCookieEnabled = true;
this.sessionIdUrlRewritingEnabled = true;
}
到这里就明白了,为啥我们改了tomcat也改了springboot本身的配置不起效果,就是因为我们是通过shiro来控制用户会话和权限控制的,
所以相当于是shiro把tomcat还有spring内部的cookie给替代了,那么我们只要定义一个bean继承自shiro的cookie注入然后放入shiro不就行了。
@Component
@ConfigurationProperties(prefix = "shiro.cookie")
public class ShiroCookie extends SimpleCookie {
}
问题到这就迎刃而解了,所以我们解决问题的时候也不能在一个方向钻牛角尖,有时候答案可能就在眼前,需要我们转变思路,
换个角度思考有可能就豁然开朗了,另外看源码确实可以一定程度上提高我们解决问题的效率。
参考资料:
- 在Intellij idea下为tomcat7设置sessionCookieName
- tomcat修改jsessionid在cookie中的名称
- Spring boot 去除URL 里的 JSESSIONID