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包出现冲突,也按照网上的方法把两个项目中 ...
随机推荐
- Codeforces #452 Div2 F
#452 Div2 F 题意 给出一个字符串, m 次操作,每次删除区间 \([l,r]\) 之间的字符 \(c\) ,输出最后得到的字符串. 分析 通过树状数组和二分,我们可以把给定的区间对应到在起 ...
- PHP使用文件流下载文件方法(附:解决下载文件内容乱码问题)
1.flush - 刷新输出缓冲 2.ob_clean - 清空(擦掉)输出缓冲区 此函数用来丢弃输出缓冲区中的内容. 此函数不会销毁输出缓冲区,而像 ob_end_clean() 函数会销毁输出缓冲 ...
- JVM GC知识回顾
这两天刚好有朋友问到我面试中GC相关问题应该怎么答,作为java面试中热门问题,其实没有什么标准回答.这篇文章结合自己之前的总结,对GC做一个回顾. 1.分代收集 当前主流VM垃圾收集都采用" ...
- Java Socket获取本机的InetAddress实例
package com.immooc;/* * InetAddress类 */import java.net.InetAddress;import java.net.UnknownHostExcept ...
- 二叉排序树BST+求树深度算法
#include "stdio.h" #include "malloc.h" typedef struct node { int key; struct nod ...
- Replacement(思维题)
题目链接:http://codeforces.com/problemset/problem/570/C C. Replacement time limit per test 2 seconds mem ...
- spring中用到的设计模式
http://www.cnblogs.com/pengmengnan/p/6717766.html 一 : 工厂模式工厂模式主要是为创建对象提供过度接口,以便将创建对象的具体 过程屏蔽隔离起来,达到提 ...
- 判断标签是否包含class的方法
if ($(this).find('i').hasClass('l-icon-wuxing')) { //取消收藏 $(this).find('i').removeClass('l-icon-wuxi ...
- 【搬运】Tea算法Java实现工具类
最近在做数据加密,目标是实现平台app的数据安全性,所以准备使用AES+Base64进行加密,适逢一个特长的json串AES加密不了,于是在谷歌了各种算法,判断是否合用,参见 各种加密算法比较 一文中 ...
- 怎么看vue版本
查看vue版本号是 vue -V 而不是npm vue -v ,npm vue -v 等同于npm -v vue -V: 后面那个V是大写的.