Tuesday, August 26, 2014

Beware: Upgrading to Tomcat 7 & Cookie Paths

We recently tried upgrading our application from Tomcat 6 to Tomcat 7.  All testing seemed to go fine in our lower environments.  However, when we began switching in our production environment and did some smoke testing, we noticed that we were getting errors, and they seemed to be related to invalid or missing sessions.

Eventually we tracked it down to a difference in the way Tomcat 7 creates JSESSIONID session cookies.  Instead of using a path of "/foo" like Tomcat 6 did, Tomcat 7 will add a trailing slash to the cookie path, or "/foo/".  This can be disabled, it turns out, by setting the sessionCookiePathUsesTrailingSlash flag to "false" on the <Context> element.

The result of this was two separate session cookies being set in the browser for the same host....one with the path (an old cookie from Tomcat 6) and one without (the new Tomcat 7 cookie).  And then browsers would send back both session cookies, since both cookie paths matched the request.  Tomcat would then (I presume) take the last JSESSIONID cookie, which may or may not have been the cookie that was set by the Tomcat 7 server.

The solution for us (after hastily rolling back the change and researching the problem) was to change the sessionCookiePathUsesTrailingSlash attribute to "false" and redeploy the change.  This caused Tomcat 7 to write cookies using "/foo" as the path, and thus the old Tomcat 6 cookie with the path of "/foo" was ovewritten (as usual) by the new cookie, since the paths matched.

Another solution to this problem would have been for us to add code to explicitly clean up the session cookie when we invalidate the session on the server.  However, it's possible this may not have helped everyone, because users can always close their browsers without logging out and thus be left with stale session cookies in their browser.  

The moral of the story: beware of changing the cookie path for your Tomcat session cookies when upgrading to Tomcat 7!