We have a web application using Jetty 8.1, dojo, and cometd that interacts between the browser and web container using (1) a JSON/HTTP REST API for synchronous operations and (2) a cometd API to receive numerous events from the server.
What we are not entirely clear on is how to elegantly manage the authentication sessions of these two different API’s especially since cometd for us will use websocket instead of regular HTTP whenever possible. The application is using form-based authentication using a standard Jetty LDAP module. So from an HTTP perspective the container provides the browser with a standard jsessionid which looks like this:
Cookie: jsessionid=758E2FAD7C199D722DA8B5E243E0E27D
Based on Simone Bordet’s post here it seems the recommended solution is to pass this token during the cometd handshake which is what we are doing.
The problem we have is there are two fundamentally different sessions – the HTTP session and the Bayeux cometd session. For reasons such as potential memory leaks and security issues, we want them to terminate in unison or to be “paired.” If a user’s HTTP session is terminated, we want the corresponding Bayeux session to terminate as well and vis-versa. Is there a recommended way of doing this?
The HTTP session and the CometD sessions have different lifecycles: for example, if there is a temporary connection failure, the CometD session will fail, and the server will ask to the client to re-handshake, thus creating a different CometD session (representing the same user, but with a different CometD
clientId). In the same case, theHttpSessionwill remain the same.Having this in mind, you need to maintain – at the application level – a mapping between a username, the correspondent
HttpSession, and the correspondentServerSession.Let’s call this mapping
HttpCometDMapper.Every time a new user logs in, you register its name (or another unique identifier of the user), the
HttpSession, and the currentServerSession.Probably you will need a two step process, where you first link the username and the
HttpSession, and then the same username with theServerSession.If a CometD re-handshake is performed, you update the mapper with the new
ServerSession.You can link the two sessions by registering an
HttpSessionListenerto theHttpSessionso that when it’s destroyed, you retrieve the current CometDServerSessionfrom the mapper and callServerSession.disconnect()on it.The viceversa is a bit trickier because CometD does not have a concept of inactivity timeout like
HttpSessionhas. It must be implemented in the application with your own logic.One part of doing it is to register a
RemoveListeneron theServerSession, like that:This listener watches for explicit disconnects from the client (and the server – beware of reentrancy).
Slightly more difficult is to implement the same mechanism for non-explicit disconnects. In this case, the
timeoutparameter will be true, but could have happened because of a temporary network failure (as opposed to the client disappearing for good), and the same user may have already re-handshaken with a newServerSession.I think in this case an application timeout could solve the issue: when you see a
ServerSessionremoved because of a timeout, you note that user and start an application timeout. If the same user re-handshakes, cancel the application timeout; otherwise the user is really gone, the application timeout expires, and you invalidate theHttpSessiontoo.What above are just ideas and suggestions; the actual implementation depends heavily on application details (and that’s why is not provided by CometD out of the box).
The key points are the mapper, the
HttpSessionListenerand theRemoveListener, and knowing the lifecycles of those components.Once you manage that, you can write the right code that does the right thing for your application.
Finally, note that CometD has a transport-agnostic way of interacting with the
HttpSessionvia theBayeuxContextinstance, that you can obtain fromBayeuxServer.getContext().I suggest that you look at that also, to see if it can simplify things, especially for retrieving tokens stored in the
HttpSession.