zoukankan      html  css  js  c++  java
  • 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;
    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";
            }
     
            @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());
                                            }
                                    }
                            }
            }
     
            
            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 !

  • 相关阅读:
    webpack介绍 安装 常用命令
    npm常用命令
    jQuery 实现点击页面其他地方隐藏菜单
    :after伪类+content内容生成经典应用举例
    几分钟前 几小时前 几天前... 7个阶段
    JS — 获取4个不重复的随机验证码
    JS — 数组去重(4种方法)
    Spring IOC原理简析
    浅谈Linux下的五种I/O模型
    大型分布式网站架构技术总结
  • 原文地址:https://www.cnblogs.com/itcomputer/p/4788952.html
Copyright © 2011-2022 走看看