tomcat中session在两个webapp中实现共享
现在遇到一个需求就是要求完成简单的单点登录,通过在一个tomcat实例中放置两个webapps应用ROOT应用和CEO应用来完成在ROOT应用登录后,在CEO可以直接使用,而未在ROOT应用登录时,不可以进去CEO应用。
实际上问题就是session如何在两个webapp中实现共享,通过上网搜索发现一个方法
方法1ServletContext
server.xml文件修改如下:
<Host name="localhost" appBase="webapps"unpackWARs="true" autoDeploy="true">
//WebappA为项目名,crossContext="true"
<Context path="/WebappA" debug="9" reloadable="true" crossContext="true"/>
<Context path="/WebappB" debug="9" reloadable="true" crossContext="true"/>
</Host>
crossContext属性的意思是:如果设置为true,你可以通过ServletContext.getContext() 调用另外一个WEB应用程序,获得ServletContext 然后再调用其getAttribute() 得到你要的对象。
Java代码如下:
WebappA:
HttpSession session = request.getSession();
session.setAttribute("userId", "test");
ServletContext ContextA =session .getServletContext();
ContextA.setAttribute("session", session );
WebappB:
HttpSession sessionB = request.getSession();
ServletContext ContextB = sessionB.getServletContext();
ServletContext ContextA= ContextB.getContext("/WebappA");// 这里面传递的是 WebappA的虚拟路径
HttpSession sessionA =(HttpSession)ContextA.getAttribute("session");
System.out.println("userId: "+sessionA.getAttribute("userId"));
初看这个方法,好像是完成我们的目标,可是在我实际应用时发现一个问题,就是当user1在登录前不可以进入CEO应用,在user1登录后才可以进入CEO应用,但是当user1退出之后,未登录的用户依然可以进入CEO应用。
后来仔细看了一下网上提供的方法,它只是在webappA的ServletContext存储了一个session值,然后传递给webAPPB,但是也仅仅只能传递一个session值,如果有两个用户的时候就会出现session覆盖。
于是探究其他解决方法。
方法2sessionCookiePath
在tomcat conf/context.html中有如下配置
- sessionCookieName
The name to be used for all session cookies created for this context. If set, this overrides any name set by the web application. If not set, the value specified by the web application, if any, will be used, or the name JSESSIONID if the web application does not explicitly set one. - sessionCookiePath
The path to be used for all session cookies created for this context. If set, this overrides any path set by the web application. If not set, the value specified by the web application will be used, or the context path used if the web application does not explicitly set one. To configure all web application to use an empty path (this can be useful for portlet specification implementations) set this attribute to / in the global CATALINA_BASE/conf/context.xml file.
Note: Once one web application using sessionCookiePath="/" obtains a session, all subsequent sessions for any other web application in the same host also configured with sessionCookiePath="/" will always use the same session ID. This holds even if the session is invalidated and a new one created. This makes session fixation protection more difficult and requires custom, Tomcat specific code to change the session ID shared by the multiple applications.
也就是说我们可以通过sessionCookiePath属性使得一个tomcat实例下所有的webapps都共享一个session,通过sessionCookieName来指定sessionCookieName名字。
于是我就在tomcat conf/context.html中配置如下:
<Context sessionCookiePath="/" sessionCookieName="SESSIONID" >
</Context>
然后在进行测试,发现在ROOT应用和CEO应用中确实sessionCookie是一样的。可是当我在ROOT中进行 session.setAttribute();时,CEO应用不能从session中取得值,为null,也就是说,对CEO应用而言,ROOT应用在session所储存的值是不可见的。然后在CEO session中进行session.setAttribute();,ROOT应用总同样无法取得CEO存储在session中的数据,猜想可能是不同的webapps并不会共享相同的session内存,每一个webapps维护自己session HashTable,后来了解到 session管理器是和context容器关联的,也就说每个web应用都会有一个session管理器,所以CEO应用当然无法从ROOT应用存储的session中取值。
方法3redis session 共享
以前曾经了解过Nginx+tomcat+redis做负载均衡的内容,知道可以把session数据存储到redis中,然后tomcat再去redis取值。
而这次的tomcat中session在两个webapp中实现共享其实也可以通过这个方法进行处理。
在tomcat conf/context.html中配置如下:
<Context sessionCookiePath="/" sessionCookieName="SESSIONID" >
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="172.22.4.16"
port="6379"
database="0"
maxInactiveInterval="60" />
</Context>
然后即可实现tomcat中session在两个webapp中实现共享。
jar包和windows redis安装包
http://pan.baidu.com/s/1eSITNnc
session过期策略
tomcat-session怎么实现的过期策略?
首先如果没有使用redis做session缓存,tomcat服务器在启动的时候初始化了一个守护线程,定期6*10秒去检查有没有Session过期.过期则清除。而使用的tomcat-session-redis做缓存,那么session过期之后就由redis进行删除,redis通过惰性删除和定期删除来删除过期的sessionID值。
当然sessionID还存在于客户端,那么客户端的sessionID清理过程是什么?
经过测试是当tomcat删除sessionID值之后,tomcat会重新生成一个sessionID值返回给客户端。

总结:
其实我这个功能就是单点登录,也就是说在A应用登录的情况下可以访问B应用,但是即使设置了sessionCookiePath,session的Attribute并没有共享,于是想到了先把session序列化到redis中,然后取出来判断,这样就可以实现单点登录。核心是session在这两个应用中必须是一样的,通过设置sessionCookiePath。
注意:
- 当你使用自己的对象执行
session.setAttribute();时,必须实现Serializable接口,不然无法进行序列化。 maxInactiveInterval不起作用
tomcat日志描述:
警告: Manager.setMaxInactiveInterval() is deprecated and calls to this method are ignored. Session timeouts should be configured in web.xml or via Context.setSessionTimeout(int timeoutInMinutes).
信息: Will expire sessions after 120 seconds(默认是30分钟)
只能通过在ROOT下的web.xml或者全局的web.xml(CEO中的session-config无法生效)中配置才可生效。<!--设置session过期时间-->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
配置成功后tomcat日志:
信息: Will expire sessions after 120 seconds- 在context中配置host为静态ip 172.22.4.16报错如下:
,Google发现原来redis和mysql一样都是已经默认绑定了localhost,只允许本机访问,于是更改redis.windows-service.conf如下bind 127.0.0.1 172.22.4.16
之后就可以使用静态ip 172.22.4.16进行访问。
- msi应用的安装,修复和卸载都是通过点击msi文件。
- 还有一个共享session的方案是spring-session。 spring-session中通过自己生成session并且存储到redis中,还是需要设置
sessionCookiePath="/"(在一个tomcat两个应用需要单点登录的情况),其他session共享方案(在多个tomcat中实现单点登录可以参考 spring session无法实现共享(多web应用)),但是spring-session不是服务器级别的,而是web 应用级别的,不受服务器如tomcat,jetty,jboss的限制。
参考文档
- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html
- 搭建Tomcat集群&通过Redis缓存共享session的一种流行方案
- Tomcat的Session过期处理策略
- Tomcat中session的管理机制
tomcat中session在两个webapp中实现共享的更多相关文章
- 使用Eclipse在Excel中找出两张表中相同证件号而姓名或工号却出现不同的的项
1:首先把Excel中的文本复制到txt中,复制如下: A表: 证件号 工号 姓名 310110xxxx220130004 101 傅家宜3101 ...
- ASP.NET中Session的sessionState 4种mode模式
1. sessionState的4种mode模式 在ASP.NET中Session的sessionState的4中mode模式:Off.InProc.StateServer及SqlServer. 2. ...
- hibernate中session
hibernate中的session是一级缓存,可以理解为进程级的缓存.在进程运行期间一直存在. session可以理解为一个可以操作数据库的对象 具体如何操作数据库? session中有方法, 如果 ...
- 如何严格设置php中session过期时间
如何严格限制session在30分钟后过期! 1.设置客户端cookie的lifetime为30分钟: 2.设置session的最大存活周期也为30分钟: 3.为每个session值加入时间戳,然后在 ...
- 第六篇 flask中session
Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 Flask 中 session 的使用 1. Flask 中 session 是 ...
- 在Django中Session的那点事!
1.session是什么 首先引入度娘的解释:Session:在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的 We ...
- 如何严格设置php中session过期时间 (转)
如何严格限制session在30分钟后过期!1.设置客户端cookie的lifetime为30分钟:2.设置session的最大存活周期也为30分钟:3.为每个session值加入时间戳,然后在程序调 ...
- (转)tomcat架构&session共享
(二期)16.tomcat的整体架构与session共享方案 [课程16]tomcat...共享.xmind47.6KB [课程16]tomcat...流程.xmind0.6MB [课程16]tomc ...
- 刚刚大学毕业,自己搭网站遇到的问题 一:tomcat中同时部署两个项目的问题
最近直接把两个项目打成war包在tomcat下发布,出现了很多莫名奇妙的问题,就是不能发布成功,只能有一个项目能成功,在网上查了很多方法,以为是两个项目中jar包出现冲突,也按照网上的方法把两个项目中 ...
随机推荐
- React Native 网络层分析
文:志俊(沪江Web前端) 本文原创,转载请注明作者及出处 在使用React Native开发中,我们熟练的采用JavaScript的方式发送请求的方式发送一个请求到服务端,但是处理这个请求的过程其实 ...
- 开发 | 微信小程序API-wx.setScreenBrightness/wx.getScreenBrightness
前言 最近接触了微信小程序 API - wx.setScreenBrightness .wx.getScreenBrightness 接口,调用该接口可以调节并显示手机屏幕亮度数据.对于喜欢腾讯新闻. ...
- python os 模块
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cdos.curdir ...
- python写unix口令破解器
看了python绝技做出来的unix口令破解器 首先需要crypt. python并不自带!! windows下pip安装失败= = 后来直接去kali敲了 附件:jiami.txt #假设是unix ...
- 51nod 1231 记分牌
链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1231 一个得分合法等价于前k小的得分之和大于等于$\frac{k* ...
- [bzoj1594] [Usaco2008 Jan]猜数游戏
二分答案(二分没冲突的前Q-1个问题),用并查集判定(用法同bzoj 1576) 假设一个询问区间[l,r],最小干草堆数目是A,我们可以得出[l,r]上的干草堆数目都>=A. 二分出mid后, ...
- vue引入新版 vue-awesome-swiper填坑
关于新版 vue-awesome-swiper 问题 为什么我的vue-awesome-swiper组件pagination小圆点不显示问题? 为什么我的vue-awesome-swiper不会自动播 ...
- C++异常层次结构
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class MyArray { publi ...
- mysql中使用show table status 查看表信息
学习标签: mysql 本文导读:在使用mysql数据库时,经常需要对mysql进行维护,查询每个库.每个表的具体使用情况,Mysql数据库可以通过执行SHOW TABLE STATUS命令来获取每个 ...
- 基于 HTML5 WebGL 的 3D 仪表数据监控
工控仪表重点发展基于现场总线技术的主控系统装置及智能化仪表.特种和专用自动化仪表:全面扩大服务领域,推进仪器仪表系统的数字化.智能化.网络化,完成 自动化仪表从模拟技术向数字技术的转变:推进具有自主版 ...