Acegi Security Not Setting a New Session Cookie
I and a colleague battled a “funny” problem, where our flash client did not get a new session cookie, when the old one expired. In the process of determining what was wrong, we came in touch with a great deal of areas, including RFC 2965 about HTTP State Management, the sources for tomcat 6, JSR-154 on the servlet 2.4 specification, and, last but certainly not least, the source code for the acegi security filter we are using.
It all boiled down to this code, in acegi class org.acegisecurity.context.HttpSessionContextIntegrationFilter:
try {
httpSession = ((HttpServletRequest) request).getSession(true);
}
catch (IllegalStateException ignored) {
}
The HttpSessionContextIntegrationFilter comes first in the acegi security filter chain configuration. What it does is to check the session for existing authentication information, and utilize that if present. If not present, acegi will continue the auth chain, to do actual authentication.
The problem is, that the above code executes after the chaining to the actual server-side call has been made. In our case, this was CXF webservice calls, that returned a good deal of data. As a consequence of this, the response had already been committed when the above code was reached, which also means the HTTP headers had been sent. Hence, no Set-Cookie header can be set by acegi at this time. Actually, an IllegalStateException is properly thrown by the container, but as the above code shows, acegi swallows this and continues. The net effect of the swallow is, that the browser gets no Set-Cookie header, and of course simply reuse the existing cookie, which points to a dead session.
In our case, the use of session to store authentication data, was done to avoid expensive calls to an authentication server internally, and by keeping a session, there was only one such call for each client login. The flash client do send authentication data on each request, to automatically relogin if session has timed out. The problem here was, that if the session had timed out just once, the client would keep on using that old session cookie, as no new one was presented to it.
The solution is simple: Simply set the option forceEagerSessionCreation to “true” for the HttpSessionContextIntegrationFilter entry. Like this, in the spring config:
<property name="forceEagerSessionCreation" value="true"/>
This will make the filter create the session up-front, before chaining the call on to the actual server-side logic. This way, the Set-Cookie header will be sent back properly, when the response commits later in the chain.
BTW: I took a quick dive into the 2.oM2 sources, where this has not changed. Maybe there are actual good reasons for just swallowing that exception(?), but would it not be good practice to tell the acegi library user, that no session could be created?


Nice catch! Sorry, bad pun, but couldn’t resist.
Seriously though, this seems pretty bad to me. Have you considered posting it to the acegi-developers mailing list?
July 19th, 2008 at 13:12[...] I am just stupid, but in my latest escapades into cookies and sessions, I noticed that a session always gets created up front in JSP pages. If you have a simple index.jsp [...]
July 21st, 2008 at 19:45