`

Tomcat实现多域名之间session共享

阅读更多

最近启用二级域名后,面临一个主域名与二级域名之间 session 不能共享的问题,带来的麻烦就是用户在主域名登陆,但由于二级域名 session 不能共享 ,因此无法进行登陆的操作,对一些功能有一些影响。

问题的原因如下
Tomcat 下,不同的二级域名,Session 默认是不共享的,因为 Cookie 名称为 JSESSIONID 的 Cookie 根域是默认是没设置的,访问不同的二级域名,其 Cookie 就重新生成,而 session 就是根据这个 Cookie 来生成的,所以在不同的二级域名下生成的 Session 也不一样。
找到了其原因,就可根据这个原因对 Tomcat 在生成 Session 时进行相应的修改。

快速解决方案1
在项目的/MET-INF/ 目录下创建一个 context.xml 文件,内容为:

1 2
<?xml version="1.0" encoding="UTF-8"?> 

<Context useHttpOnly="true" sessionCookiePath="/"sessionCookieDomain=".XXXX.com" />

Done!

快速解决方案2:修改 Tomcat 的 server.xml 文件,内容为:

1
<Context path="" docBase="ROOT" reloadable="false"

 useHttpOnly="true"sessionCookiePath="/" sessionCookieDomain=".XXXX.com" />

Done!

以上两种方案的详细讲解见:http://tomcat.apache.org/tomcat-6.0-doc/config/context.html

快速解决方案3
:生成一个叫做 crossSubdomainSessionValve.jar 的文件,用的时候放在 Tomcat lib 目录下,然后修改 Tomcat server.xml 文件:

1
<Valve className="me.seanchang.CrossSubdomainSessionValve" />



原理:取代由 Tomcat 域产生的会话 cookie ,允许该会话 cookie 跨子域共享。

代码:

 
package me.seanchang; import java.io.IOException; import java.util.logging.Level; importjava.util.logging.Logger; import javax.servlet.ServletException; importjavax.servlet.http.Cookie; import org.apache.catalina.Globals; importorg.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; importorg.apache.catalina.valves.ValveBase; import org.apache.tomcat.util.buf.MessageBytes; importorg.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.ServerCookie; publicclass CrossSubdomainSessionValve extends ValveBase { private static Logger log =Logger.getLogger("CrossSubdomainSessionValve"); public CrossSubdomainSessionValve() { super();info = "me.seanchang.CrossSubdomainSessionValve/1.0"; } @Override public void invoke(Requestrequest, Response response) throws IOException, ServletException { // this will cause Request.doGetSession to create the session cookie if // necessary request.getSession(true); // replace any Tomcat-generated session cookies with our own Cookie[] cookies =response.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; log.info("CrossSubdomainSessionValve: Cookie name is " + cookie.getName());if (Globals.SESSION_COOKIE_NAME.equals(cookie.getName())) replaceCookie(request, response, cookie); } } // process the next valve getNext().invoke(request, response); } protected voidreplaceCookie(Request request, Response response, Cookie cookie) { // copy the existing session cookie, but use a different domain Cookie newCookie = new Cookie(cookie.getName(), cookie.getValue()); if(cookie.getPath() != null) newCookie.setPath(cookie.getPath());newCookie.setDomain(getCookieDomain(request)); newCookie.setMaxAge(cookie.getMaxAge());newCookie.setVersion(cookie.getVersion()); if (cookie.getComment() != null)newCookie.setComment(cookie.getComment()); newCookie.setSecure(cookie.getSecure()); // if the response has already been committed, our replacement strategy // will have no effect MimeHeaders headers = new MimeHeaders(); if (response.isCommitted()) log.info("CrossSubdomainSessionValve: response was already committed!"); // find the Set-Cookie header for the existing cookie and replace its // value with new cookie headers = response.getCoyoteResponse().getMimeHeaders(); for(int i = 0, size = headers.size(); i < size; i++) { if (headers.getName(i).equals("Set-Cookie")){ MessageBytes value = headers.getValue(i); if (value.indexOf(cookie.getName()) >= 0) {StringBuffer buffer = new StringBuffer(); ServerCookie .appendCookieValue(buffer, newCookie.getVersion(), newCookie.getName(), newCookie.getValue(), newCookie.getPath(), newCookie.getDomain(), newCookie.getComment(), newCookie.getMaxAge(), newCookie.getSecure(),true); log.info("CrossSubdomainSessionValve: old Set-Cookie value: " + value.toString());log.info("CrossSubdomainSessionValve: new Set-Cookie value: " + buffer);value.setString(buffer.toString()); } } } } protected String getCookieDomain(Request request) {String cookieDomain = request.getServerName(); String[] parts = cookieDomain.split("\\."); if(parts.length >= 2) cookieDomain = parts[parts.length - 2] + "." + parts[parts.length - 1];return "." + cookieDomain; } public String toString() turn ("CrossSubdomainSessionValve[container="+ container.getName() + ']'); } }

将以上代码导出一个jar文件,放入 $CATALINA_HOME/lib 中,修改 $CATALINA_HOME/conf/server.xml 文件,加入

1
<Valve className="me.seanchang.CrossSubdomainSessionValve" />

重启 Tomcat ,Done !

 

分享到:
评论
1 楼 yin_bp 2016-01-19  
可以使用跨平台解决方案:bboss会话共享框架来实现Tomcat多域名之间session共享:

http://yin-bp.iteye.com/blog/2079685

相关推荐

    Tomcat二级域名Session共享例子

    Tomcat二级域名Session共享例子,具体操作看博客:http://blog.csdn.net/luogqing/article/details/78595200

    Java Tomcat二级域名Session共享例子

    Tomcat二级域名Session共享例子,具体操作看博客:http://blog.csdn.net/luogqing/article/details/78595200

    tomcat二级域名session共享包

    方便新手使用的tomcat二级域名所需要的包.. 详细的使用方法.查看.. http://blog.csdn.net/wqfeng520/archive/2010/11/29/6042596.aspx

    nginx+tomcat多域名配置

    "nginx+tomcat多域名配置"就是一种高效且灵活的解决方案,它结合了Nginx作为前端反向代理服务器和Tomcat作为后端应用服务器的优势。下面将详细介绍这个配置的原理、步骤以及注意事项。 1. **Nginx与Tomcat的角色**...

    一个服务器搭多个tomcat导致session丢失,或者同一个IP不同端口,多个应用的session会冲突解决方法

    一个服务器上搭建了多个tomcat或者weblogic,端口不一样,同时启动访问时session丢失。如:A,B两个服务,在浏览器中登录访问A后,当前打开的浏览器上在开一个选项卡访问B服务后,回过来点击访问A时session丢失,...

    tomcat-redis-session-manager

    《Tomcat与Redis整合实现Session共享详解》 在分布式系统中,Session共享是一个常见的需求,尤其是在基于Java的Web应用中,Tomcat作为常用的Servlet容器,如何有效地管理并共享用户Session信息是一个重要的议题。...

    tomcat 8.5.x | 9.x.x redis cluster session

    通过以上步骤,你已经成功地在Tomcat 8.5.x或9.x.x中实现了基于Redis Cluster的session共享。这将大大提高系统的可扩展性和可用性,同时降低单点故障的风险。记住,根据实际环境进行调整和优化是至关重要的,以确保...

    nginx+memcached+tomcat

    本文将介绍如何使用`nginx`、`memcached`和`tomcat`搭建一个高可用的集群环境,实现负载均衡和Session共享。 1. **Nginx环境搭建**: Nginx是一款高性能的HTTP和反向代理服务器,它能够处理静态文件、动态内容、...

    nginx+redis+tomcat共享信息

    - **Session共享**:通过将session信息存储在Redis中,多台Tomcat服务器可以共享用户状态,实现负载均衡下的会话持久化。 - **缓存机制**:Redis还可以作为应用程序的数据缓存,加快数据访问速度,减少对数据库的...

    apache+tomcat+memcached 全配置

    - 使用 Apache 的 Proxy 或 Proxy Balancer 模块实现多个 Tomcat 实例之间的负载均衡。 - 配置好各个 Tomcat 实例的地址和端口,让 Apache 负责分发请求。 - **Session 共享** - 利用 Memcached 作为 Session ...

    Session详解.doc

    #### 七、跨应用程序的Session共享 在一些复杂的Web应用程序中,可能需要在不同的应用程序之间共享Session数据。实现这一目标的方法包括: - **数据库存储**:将Session数据存储在数据库中,所有应用程序都可以访问...

    tomcat集群

    10. **虚拟主机**:在集群环境中,可以配置多个虚拟主机,使得不同的域名或应用可以运行在同一组Tomcat实例上,充分利用资源。 综上所述,Tomcat集群通过负载均衡、故障转移、会话管理等机制,实现了高可用性和可...

    集中式session管理方案(2)

    集中式Session管理方案是一种在分布式环境中解决多个应用服务器之间共享用户会话状态的技术。这种方案主要解决了在多台服务器上部署的应用系统如何协同处理用户的Session数据,确保用户在不同服务器间的无缝切换,...

    apache+tomcat集群配置64位windows系统

    总结,配置Apache和Tomcat集群涉及多个环节,包括Apache的负载均衡配置、Tomcat的集群设置、session共享以及故障转移和会话持久化策略。每个环节都需要细致操作,以确保在64位Windows系统上实现稳定、高效的Web服务...

    tomcat的内部原理

    了解这些核心概念后,我们可以更有效地管理Tomcat,包括调整Connector的线程池、设置Session管理策略、优化Context的加载速度以及配置Host以支持多域名应用。同时,掌握这些内部原理也有助于排查和解决应用程序运行...

    apache-tomcat-7.0.42

    7. **Cluster**:对于需要高可用性和负载均衡的环境,Tomcat 7支持集群功能,可以将多个Tomcat实例组成一个集群,共享session数据,实现故障转移和负载分担。 8. **Manager App**:内置的管理工具,允许管理员通过...

    使用 CAS 在 Tomcat6 中实现单点登录

    【单点登录(SSO)】单点登录(Single Sign On,简称SSO)是一种让用户在多应用系统间共享同一登录状态的技术,用户只需登录一次,即可访问所有相互信任的应用系统,大大提升了用户体验。 【CAS(Central ...

Global site tag (gtag.js) - Google Analytics