That's a good point Matthias - in my case sessions are always created so it's
acceptable.  Can you think of a good way to only replace the session cookie
when it would be naturally created by the app for those cases where always
creating it is not acceptable?

Note that this entire issue would be made much more simple if there was an
easy way to override the
org.apache.catalina.connector.Request.configureSessionCookie method.  I have
not found an easy way to do that.

Thanks,
Zach



Reich, Matthias wrote:
> 
> With your implementation, the valve will have the effect that a session
> is created upon first access to a server, 
> not only when required by the application.
> (see also discussion on
> http://www.nabble.com/Cookie-less-session-tracking---whats-are-the-downs
> ides-tp16738472p16738472.html )
> 
> Thus, the valve is only suitable if this behavior is acceptable.
> (e.g. if you can be sure that your site is not accessed by search engine
> robots, if you have a rather short session timeout and can live with the
> overhead of creating many unnecessary session objects, ...)
> 
> -- Matthias
> 
> -----Original Message-----
> From: Zach Cox [mailto:[EMAIL PROTECTED] 
> Sent: Saturday, April 19, 2008 10:26 PM
> To: users@tomcat.apache.org
> Subject: Share session cookie across subdomains
> 
> I'm working on a site that has a single web app in Tomcat that handles
> lots of subdomains via wildcard DNS:
>  - site.com
>  - www.site.com
>  - sub1.site.com
>  - sub2.site.com
>  - etc.
> 
> Basically, the site content gets customized based on the subdomain in
> the request, if any.  However I ran into a problem where Tomcat would
> use separate JSESSIONID session cookies on each different domain which
> causes problems as the user would have multiple sessions if they
> switched subdomains.
> 
> I found an examle Valve at http://www.esus.be/blog/?p=3 but it
> ultimately did not result in a cross-subdomain session cookie (at
> least in the Tomcat 6.0.14 I'm using).  I'm posting the Valve that did
> actually seem to solve the problem for me below in hopes that it will
> help someone else with the same problem in the future.
> 
> Basically you end up with a single session cookie with its domain set
> to .site.com so the client will send it back in the request for any
> subdomain.
> 
> 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
> 
> If you see/experience any problems please let me know!
> 
> Thanks,
> Zach
> 
> 
> 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
> [EMAIL PROTECTED] 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="Catalina"...&gt;
>  *     &lt;Valve
> className="org.three3s.valves.CrossSubdomainSessionValve"/&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];
>                 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() + ']');
>     }
> }
> 
> ---------------------------------------------------------------------
> To start a new topic, e-mail: users@tomcat.apache.org
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 
> ---------------------------------------------------------------------
> To start a new topic, e-mail: users@tomcat.apache.org
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 
> 

-- 
View this message in context: 
http://www.nabble.com/Share-session-cookie-across-subdomains-tp16787390p16807270.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to