Apache Tomcat 7 Changing JSESSIONID on Every Request

Nobody picture Nobody · Jan 22, 2013 · Viewed 19.7k times · Source

This issue is driving me insane, so maybe someone could help me understand what the issue is. I have a tomcat web application being fronted by HAProxy. HAProxy is also doing SSL offloading, and is configured to use sticky sessions. I am using Tomcat's session replication feature which seems to be working just fine. The sessions appear on both appservers.

For some reason, Tomcat is generating a new JSESSIONID for every single web request, and then copying the contents of the old session into the new session. That is to say, my session contents are still there within the new session, but a new ID is generated and sent back to the client. But it only does this for my web application. It does not do this for the /manager application.

I have tried every trick in the book, such as setting this in my context.xml:

<Valve className="org.apache.catalina.authenticator.BasicAuthenticator" changeSessionIdOnAuthentication="false" />

And setting these attributes on my Context element:

<Context path="/myapp" reloadable="false" override="true" useNaming="false" allowLinking="true" useHttpOnly="false" sessionCookiePath="/" sessionCookiePathUsesTrailingSlash="false">

And still, the result is the same. Tomcat generates a new session id with every request and copies the contents of the old session into the new id.

I would suspect it had something to do with HAProxy, except that the /manager application is also behind HAProxy and it does not exhibit this behavior.

Why is Tomcat doing this, and what can I do to prevent it?

Answer

Nobody picture Nobody · Jan 24, 2013

Turns out that it was cause by Spring Security. We are using Spring Security 3.1x, and by default it stores the authenticated credentials in the user's session. And to counter session fixation attacks, it automatically copies the contents of the user's session to a new session id and invalidates the old session.

The fix was to add the following to the http element in the security configuration, since we don't need to use the session in our application:

create-session="stateless"

Hopefully this helps someone else down the line.