tomcat 二级域名 session共享

Tomcat下,不同的二级域名之间或根域与子域之间,Session默认是不共享的,因为Cookie名称为JSESSIONID的Cookie根域是默认是没设置 的,访问不同的二级域名,其Cookie就重新生成,而session就是根据这个Cookie来生成的,所以在不同的二级域名下生成的Session也 不一样。找到了其原因,就可根据这个原因对Tomcat在生成Session时进行相应的修改(注:本文针对Tomcat 6.0.18)。

修改tomcat源代码 包:catalina.jar 
类:org.apache.catalina.connector.Request

protected void configureSessionCookie(Cookie cookie) {       
  cookie.setMaxAge(-1); 
        String contextPath = null; 
        if (!connector.getEmptySessionPath() && (getContext() != null)) { 
            contextPath = getContext().getEncodedPath();       
  } 
        if ((contextPath != null) && (contextPath.length() > 0)) {       
      cookie.setPath(contextPath);        
 } else { 
            cookie.setPath("/");         } 
        String value = System.getProperty("webDomain");     
    if ((null !=value) && (value.length()>0) && (value.indexOf(".") != -1)) { 
            cookie.setDomain((value.startsWith("."))?value:"."+value);     
    } 
        if (isSecure()) { 
            cookie.setSecure(true);         }   
  }

重新编译Tomcat:编译tomcat  
修改配置:tomcat\conf\catalina.properties,在最后添加一行 webDomain=***.com

网上其他方案

Usage: 
 - compile CrossSubdomainSessionValve & put it in a .jar file 
 - put that .jar file in $CATALINA_HOME/lib directory 
 - include a <Valve className="org.three3s.valves.CrossSubdomainSessionValve"/> in 
$CATALINA_HOME/conf/server.xml

package org.three3s.valves;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.catalina.*;
import org.apache.catalina.connector.*;
import org.apache.catalina.valves.*;
import org.apache.tomcat.util.buf.*;
import org.apache.tomcat.util.http.*;

/** <p>Replaces the domain of the session cookie generated by Tomcat
with a domain that allows that
 * session cookie to be shared across subdomains.  This valve digs
down into the response headers
 * and replaces the Set-Cookie header for the session cookie, instead
of futilely trying to
 * modify an existing Cookie object like the example at
http://www.esus.be/blog/?p=3.  That
 * approach does not work (at least as of Tomcat 6.0.14) because the
 * <code>org.apache.catalina.connector.Response.addCookieInternal</code>
method renders the
 * cookie into the Set-Cookie response header immediately, making any
subsequent modifying calls
 * on the Cookie object ultimately pointless.</p>
 *
 * <p>This results in a single, cross-subdomain session cookie on the
client that allows the
 * session to be shared across all subdomains.  However, see the
{@link getCookieDomain(Request)}
 * method for limits on the subdomains.</p>
 *
 * <p>Note though, that this approach will fail if the response has
already been committed.  Thus,
 * this valve forces Tomcat to generate the session cookie and then
replaces it before invoking
 * the next valve in the chain.  Hopefully this is early enough in the
valve-processing chain
 * that the response will not have already been committed.  You are
advised to define this
 * valve as early as possible in server.xml to ensure that the
response has not already been
 * committed when this valve is invoked.</p>
 *
 * <p>We recommend that you define this valve in server.xml
immediately after the Catalina Engine
 * as follows:
 * <pre>
 * <Engine name="Catalina"...>
 *     <Valve className="org.three3s.valves.CrossSubdomainSessionValve"/>
 * </pre>
 * </p>
 */
public class CrossSubdomainSessionValve extends ValveBase
{
    public CrossSubdomainSessionValve()
    {
        super();
        info = "org.three3s.valves.CrossSubdomainSessionValve/1.0";
    }

    @Override
    public void invoke(Request request, 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];
                containerLog.debug("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);
    }

    /** Replaces the value of the response header used to set the
specified cookie to a value
     * with the cookie‘s domain set to the value returned by
<code>getCookieDomain(request)</code>
     *
     * @param request
     * @param response
     * @param cookie cookie to be replaced.
     */
    @SuppressWarnings("unchecked")
    protected void replaceCookie(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
        if (response.isCommitted())
            containerLog.error("CrossSubdomainSessionValve: response
was already committed!");

        //find the Set-Cookie header for the existing cookie and
replace its value with new cookie
        MimeHeaders 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());
                    containerLog.debug("CrossSubdomainSessionValve:
old Set-Cookie value: "
                            + value.toString());
                    containerLog.debug("CrossSubdomainSessionValve:
new Set-Cookie value: " + buffer);
                    value.setString(buffer.toString());
                }
            }
        }
    }

    /** Returns the last two parts of the specified request‘s server
name preceded by a dot.
     * Using this as the session cookie‘s domain allows the session to
be shared across subdomains.
     * Note that this implies the session can only be used with
domains consisting of two or
     * three parts, according to the domain-matching rules specified
in RFC 2109 and RFC 2965.
     *
     * <p>Examples:</p>
     * <ul>
     * <li>foo.com => .foo.com</li>
     * <li>www.foo.com => .foo.com</li>
     * <li>bar.foo.com => .foo.com</li>
     * <li>abc.bar.foo.com => .foo.com - this means cookie won‘t work
on abc.bar.foo.com!</li>
     * </ul>
     *
     * @param request provides the server name used to create cookie domain.
     * @return the last two parts of the specified request‘s server
name preceded by a dot.
     */
    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()
    {
        return ("CrossSubdomainSessionValve[container=" +
container.getName() + ‘]‘);
    }
}

放入<Host>标签中,也可以放到<Engine>标签中。个人猜想:如果放入<Host>标签中应该只是当前项目的主域名和二级域名session共享,如果放到<Engine>标签中,应该是该tomcat下所有的项目都是主域名和二级域名共享(没有实验)。

方便对于tomcat的二级域名的使用..而导致session失效的解决方法..

需要引用的包是..

下载CrossSubdomainSessionValve包.. 把下载的包,放到$CATALINA_HOME/server/lib 里面

然后修改tomcat的配置文件: $CATALINA_HOME/conf/server.xml

在标签"Engine",中添加依家配置标签..

<Valve className="org.three3s.valves.CrossSubdomainSessionValve"/>

类似于:

<Engine name="Catalina"...>    
       <valve className="org.three3s.valves.CrossSubdomainSessionValve"/>

</Engine>

这是简单方案。 多台服务器的话,还需要配置tomcat的session复制。
大型项目出于性能考虑,一般采用session分布式方案,如: 修改session实现+分布式缓存memcached

Memcache存储session,修改tomcat源码,实现全站二级域名session共享 http://blog.csdn.net/jimmy1980/article/details/4975476
使用memcache实现session共享 http://blog.csdn.net/jimmy1980/article/details/4981410

tomcat 二级域名 session共享

时间: 2024-08-10 02:26:35

tomcat 二级域名 session共享的相关文章

二级域名session 共享方案

二级域名session 共享方案 1.利用COOKIE存放session_id(); 实例: 域名一文件php代码: <?php session_start(); setcookie("session_id",session_id(),time()+3600*24*365*10,"/",".session.com"); $_SESSION['user_name'] = '梁山良民'; echo $_SESSION['user_name'];

asp.net 二级域名session共享

1.自定义类 namespace SessionShare{ public class CrossDomainCookie : IHttpModule { private string m_RootDomain = string.Empty;#region IHttpModule Memberspublic void Dispose() {}public void Init(HttpApplication context) { m_RootDomain = ConfigurationManage

JSP,JAVAWEB通过配置web.xml完成主/二级域名Session共享

As we all 知道.web应用中一般根据cookie id来完成Session支持以便于用户跟踪,在顶级域名如 a.com和www.a.com 之间的Session和Cookie默认情况是无法共享的,这是因为Cookie根据Domain属性来决定归属.通过Chrome系浏览器的F12调试工具我们可以看到a.com的默认Domain是a.com而www.a.com的默认Domain是www.a.com,可能他们都访问的是同一个站点,但是这两个Domain属性值不一致导致了如果在a.com基于

ASP.NET二级域名站点共享Session状态

前面一篇文章提到了如何在使用了ASP.NET form authentication的二级站点之间共享登陆状态, http://www.cnblogs.com/jzywh/archive/2007/09/23/902905.html, 今天, 我要写的是如何在二级域名站点之间,主站点和二级域名站点之间共享Session. 首先, Session要共享,站点之间SessionID必须要一致,那怎么保证SessionID一致呢? ASP.NET中的SessionID是存储在客户端的cookie之中键

nginx+memcached+tomcat集群 session共享完整版

nginx+memcached+tomcat集群 session共享完整版 集群环境 1.nginx版本 nginx-1.6.2.tar.gz 2.jdk 版本 jdk-7u21-linux-x64.tar.gz 3.tomcat 版本  7.0.29 4.memcached 版本 memcached-1.4.22.tar.gz 5. CentOS 6.5 系统采用一台服务做测试 一.nginx安装 安装依赖包 yum -y install gcc gcc-c++ 1.安装pcre库 tar z

【Tomcat】Tomcat + Memcached 实现session共享

概述 web项目中,Tomcat的访问量总是有限的,这时候就需要用到Tomcat集群,多个Tomcat的时候就要考虑Session共享的问题,这里介绍一种使用Memcached做Session共享的解决方案 环境 操作系统:Linux( centOS 6..5 版) 软件:Tomcat7    Memcached 实现原理 Tomcat + Memcached 实现session共享流程图 配置 安装Tomcat 2个和Memcached 1个,参考[Linux]Tomcat安装及一个服务器配置

Tomcat+Memcached实现Session共享

在先前的例子中,我用Tomcat官方提供的Session复制方式实现Tomcat集群Session共享.今天,我用另一种方式Memcached-Session-Manager来实现Session共享.话不多说,上实例. Memcached-Session-Manager将Session序列化到Memcache中,序列化的组件有很多,比如: msm-kryo-serializer.msm-javolution-serializer等,这里使用msm-javolution-serializer,使用

160512、nginx+多个tomcat集群+session共享(windows版)

第一步:下载nginx的windows版本,解压即可使用,点击nginx.exe启动nginx 或cmd命令 1.启动: D:\nginx+tomcat\nginx-1.9.3>start nginx或D:\nginx+tomcat\nginx-1.9.3>nginx.exe注:建议使用第一种,第二种会使你的cmd窗口一直处于执行中,不能进行其他命令操作. 2.停止: D:\nginx+tomcat\nginx-1.9.3>nginx.exe -s stop或D:\nginx+tomca

tomcat篇之结合apache+tomcat+memcached做session共享

tomcat1:192.168.1.155 tomcat2:192.168.1.11 apache:192.168.1.155 前端代理apache设置,参考前面的tomcat文章(基于mod_proxy和mod_jk模块) 这里不再赘述,直接贴配置文件: cd /etc/httpd/conf.d [[email protected] conf.d]# cat mod_jk.conf LoadModule  jk_module  modules/mod_jk.so JkWorkersFile/e