同一tomcat下实现多应用session共享 单点登录

再见尼罗河 2017-05-06 07:02:36
随着web开发的应用程序越来越来,我么可能会将原有的一个应用拆分多多了应用,同时也应该支持新增加的应用扩展,
同时又希望通过单点登录统一管理所有的应用,现在有很多比较流行的技术实现 比如cas单点登录,restful令牌等等。
cookie共享等等,但是结余我们很多应用是很久之前开发的,使用session来管理,未考虑扩展,新的应用想集成进来时不免遇到困难,这里提供一种解决方案
同一tomcat下实现多应用session共享,实现单点登录


通过主应用ContextA实现单点登陆

1.tomcat server.xml 开启crossContext共享

<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">

<Context path="/ContextA" debug="9" reloadable="true" crossContext="true"/>
<Context path="/ContextB" debug="9" reloadable="true" crossContext="true"/>

</Host>



2.主应用ContextA 登录后设置session到ServletContext
这里设置用户id admin 作为 ServletContext键 因此不支持一个账号多处同时登录
session.getServletContext().setAttribute("admin", session);


3.应用ContextB 登录页
ServletContext ContextB = session.getServletContext();  
ServletContext ContextA= ContextB.getContext("/ContextA");// 这里面传递的是 ContextA的虚拟路径
HttpSession sessionA =(HttpSession)ContextA.getAttribute("admin");
if (sessionA != null) {
try{
Object attribute = sessionA.getAttribute("user");
if(attribute!= null){
System.out.println("user: "+attribute);
session.setAttribute("user", attribute);
//TODO:已经登录跳转到首页
}
}catch(IllegalStateException e){
System.out.println("ContextA session 已经失效");
}

}


4.通过以上步奏session共享是解决了,但是如果在主应用或子应用中登出,或着session到期,存在ServletContext 中的session是没办法销毁的,导致session失效无法同步,这种情况可以采用HttpSessionListener监听session销毁,同步其他应用的session

设置HttpSessionListener 实现session失效同步
ContextA:

import javax.servlet.http.HttpSessionListener;  
import javax.servlet.http.HttpSessionEvent;

public class SessionCounter implements HttpSessionListener {
private static int activeSessions =0;
/* Session创建事件 */
public void sessionCreated(HttpSessionEvent se) {

}
/* Session失效事件 */
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ContextA=se.getSession().getServletContext();
ServletContext ContextB= ContextA.getContext("/ContextB");
HttpSession sessionB =(HttpSession)ContextB.getAttribute("admin");
if (sessionB != null) {
sessionB.invalidate();
}


}
}


ContextB:

import javax.servlet.http.HttpSessionListener;  
import javax.servlet.http.HttpSessionEvent;

public class SessionCounter implements HttpSessionListener {
private static int activeSessions =0;
/* Session创建事件 */
public void sessionCreated(HttpSessionEvent se) {

}
/* Session失效事件 */
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ContextB=se.getSession().getServletContext();
ServletContext ContextA= ContextA.getContext("/ContextA");
HttpSession sessionA =(HttpSession)ContextA.getAttribute("admin");
if (sessionA != null) {
sessionA.invalidate();
}
}
}




}

web.xml配置session监听器
<listener>  
<listener-class>demo.listener.SessionCounter</listener-class>
</listener>


扩展:示例是两个应用实现共享,如果有多个应用可以在主登录应用ServletContext维护一个包含所有子应用的context列表,具体操作遍历即可
...全文
1376 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
爱吃窝窝头 2020-11-11
  • 打赏
  • 举报
回复
引用 5 楼 suifengyuluo 的回复:
context.xml里配置<Context sessionCookiePath="/" > 就搞定了
老哥牛逼, 正需要这种解决方案
再见尼罗河 2017-09-06
  • 打赏
  • 举报
回复
引用 7 楼 再见尼罗河的回复:
是另外一个servletcontext
每一个tomcat应用对应的上下文根
再见尼罗河 2017-09-06
  • 打赏
  • 举报
回复
是另外一个servletcontext
溜溜侠 2017-08-10
  • 打赏
  • 举报
回复
你好,ServletContext ContextA= ContextA.getContext("/ContextA");这个"/ContextA"具体指的是什么,能举个例子吗
suifengyuluo 2017-05-17
  • 打赏
  • 举报
回复
context.xml里配置<Context sessionCookiePath="/" > 就搞定了
suifengyuluo 2017-05-17
  • 打赏
  • 举报
回复
tomcat支持配置cookie的全局配置,你可以看看,加个配置就能实现sessionId相同了
再见尼罗河 2017-05-14
  • 打赏
  • 举报
回复
引用 2 楼 suifengyuluo 的回复:
这样配置了以后同一个浏览器访问两个项目产生的sessionId不相同,只通过用户数据是否存在于session中判断,那一个用户登录了,我在其他哪个客户端都可以直接访问了么
只要有一个客户端登陆,其他客户端都可能访问。这个问题是的确存在的,多谢指出。 我目前的解决方式是在 contextA session设置时记录一个请求ip地址和mac地址,contextB主页增加判断当前请求ip地址和contextA中取出的ip地址和mac地址比较是否一致,一致则认为是同一客户端登录。 增加mac地址判断考虑到移动大内网等情况对外暴露的都是同一IP地址。 当然这种方式有点low,如果原有系统条件允许的话,建议还是用redis等存储会话信息。
suifengyuluo 2017-05-11
  • 打赏
  • 举报
回复
这样配置了以后同一个浏览器访问两个项目产生的sessionId不相同,只通过用户数据是否存在于session中判断,那一个用户登录了,我在其他哪个客户端都可以直接访问了么
李德胜1995 2017-05-06
  • 打赏
  • 举报
回复

81,091

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧