Tomcat实现多域名之间session共享

2 篇文章 0 订阅

转载自:http://blog.sina.com.cn/s/blog_69a890b301015zc6.html

-----------------------------------以下是原文----------------------------------

最近启用二级域名后,面临一个主域名与二级域名之间 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.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;

 
import org.apache.catalina.Globals;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.ServerCookie;


public class CrossSubdomainSessionValve extends ValveBase {
  private static Logger log = Logger.getLogger("CrossSubdomainSessionValve");

  public CrossSubdomainSessionValve() {
    super();
    info = "me.seanchang.CrossSubdomainSessionValve/1.0";
  }

  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;
  }

  @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];

        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 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
    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());
        }
      }
    }
  }

  public String toString() {
    return ("CrossSubdomainSessionValve[container=" + container.getName() + ']');
  }
}

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

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

重启 Tomcat ,Done !

 

引用自:http://blog.seanchang.me/tomcat-to-achieve-the-main-domain-name-session-sharing-between-subdomains.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值