world_eyes

          記錄點滴的地方

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            10 隨筆 :: 3 文章 :: 1 評論 :: 0 Trackbacks

               Tomcat下,不同的二級域名,Session默認是不共享的,因為Cookie名稱為JSESSIONID的Cookie根域是默認是沒設置的,訪問 不同的二級域名,其Cookie就重新生成,而session就是根據這個Cookie來生成的,所以在不同的二級域名下生成的Session也不一樣。 找到了其原因,就可根據這個原因對Tomcat在生成Session時進行相應的修改(注:本文針對Tomcat 6.0)。

               單個web項目運行在tomcat上但是卻使用多個子域名,如:

           - site.com
           - www.site.com
           - sub1.site.com
           - sub2.site.com
           - etc.

           

          這樣會導致session的不能共享,在網絡上查找的并卻最快的解決辦法。

           

          解決辦法:

          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>
           * &lt;Engine name=&quot;Catalina&quot;&gt;
           *     &lt;Valve
           * className=&quot;org.three3s.valves.CrossSubdomainSessionValve&quot;/&gt;
           * </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];
                          
          // System.out.println("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.
               
          */
              
          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());
                  
          // System.out.println("CrossSubdomainSessionValve: CookiePath is " +
                  
          // cookie.getPath());
                  if (cookie.getPath() != null) newCookie.setPath(cookie.getPath());
                  String domain 
          = getCookieDomain(request);
                  
          if (!".piaoyoo.com".equals(domain)) domain = request.getServerName();
                  
          // System.out.println("CrossSubdomainSessionValve: CookieDomain is " +
                  
          // domain);
                  newCookie.setDomain(domain);
                  newCookie.setMaxAge(cookie.getMaxAge());
                  newCookie.setVersion(cookie.getVersion());
                  
          // System.out.println("CrossSubdomainSessionValve: CookieComment is " +
                  
          // cookie.getComment());
                  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()) System.out.println("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());
                              
          // System.out.println("CrossSubdomainSessionValve: old Set-Cookie value: "
                              
          // + value.toString());
                              
          // System.out.println("CrossSubdomainSessionValve: new Set-Cookie value: "
                              
          // + buffer);
                              
          // System.out.println("-----------------------------");
                              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() + ']');
              }
          }



          posted on 2010-06-04 17:17 world_eyes 閱讀(1682) 評論(0)  編輯  收藏 所屬分類: JAVA

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 饶阳县| 崇阳县| 禄丰县| 股票| 牟定县| 阿坝县| 溧阳市| 都兰县| 延津县| 青川县| 行唐县| 梅河口市| 天全县| 扶余县| 扶沟县| 云阳县| 天门市| 武平县| 嘉定区| 成都市| 昌图县| 女性| 嘉义县| 昌江| 临高县| 霍山县| 禄丰县| 乌兰察布市| 辽源市| 盐津县| 永吉县| 阳春市| 清徐县| 砚山县| 高雄市| 盘山县| 宿松县| 新邵县| 澄迈县| 临武县| 中宁县|