I have having a spot of bother managing the session timeout with a simple application based on MyFaces and Richfaces running on Tomcat.
1) When the session expires, gracefully clean up
2) When someone navigates directly to a page and does not have a session, send them to the login page.
3) After a person's session has timed out, show a timeout page and then redirect to the login page.
The first two are easy. I simply defined a listener and filter in the web.xml. One listening to for session expiry (safely closing connections, cleaning up temp files etc.) and the other checking if they have a valid session; if not, redirecting to the login page.
For the third I have been trying a number of things and getting no where fast. My main issue is trying to tell the difference between a new user trying to skip past the login page and an existing user whose session has timed out.
I've tried a PhaseListener, but that didn't quite work; I've tried adding an error-page definition for javax.faces.application.ViewExpiredException to the web.xml, but that exception does not seem to get thrown after the session expires, it seems to try and re-load the backing bean and then crashes with a NPE in my code (because session information is missing).
I tried with the PhaseListener doing an ExternalContext.redirect as well as setting a navigation rule. When it tried to follow the navigation rule after the session expired, Faces said the context could not be found.
It's as if I can't separate requirements 2 and 3. I'm not looking for anyone to write code for me or anything - I just can't see a way to gracefully handle these two scenarios. I am sure there is one and I'm probably trying to over-complicate things. Does nayone know how to do this and is willing to give me a few pointers?
My main issue is trying to tell the difference between a new user trying to skip past the login page and an existing user whose session has timed out.
If you even bother, you're doing more than most Do-it-Yourself security systems do. Which is one (of many!) reasons why I recommend using J2EE standard container-based security instead of a roll-your own system. Container-based security can be set to watch URLs and if the user attempt to access a guarded URL, the app container will immediately hijack the request and force a login. If the user fails to login, the webapp never even sees the URL request. A request that's not delivered is one that can't do damage.
That doesn't mean I have a "perfect" solution. JSF is horribly bad about how it handles session timeouts, and even JSF2 doesn't completely fix that. But that's a problem in JSF, regardless of what security system you use.
An IDE is no substitute for an Intelligent Developer.
Joined: Jun 09, 2009
I have managed to use a filter to get the desired result (I did have a new PhaseListener written, but it seems AJAX can't do a redirect cleanly).
The filter will for people to login if they don't have a session or send them to the timeout page if it works out their session has simply expired. This approach seems to work for AJAX as well.
It would be nice if I could rely on the container, but as I don't know what container (or even if it will be a full J2EE container) they will be using or what other apps it may be running alongside mine - I want to make sure the application can cope with it itself.
I doubt my approach is deal, but it's the best I can do just now I think.
You CAN rely on the container. Even Tomcat fully supports this feature (minus the EJB parts), and it's mandatory for any container that wants to claim the "J(2)EE compliant" label.
What does vary is how you set up the credentials, but that's an external thing that has no impact on how you code and configure your webapp. That's part of the beauty of the architecture. I can code and debug the app with minimal effort spent on security code and its potential for complicating the business logic, then add the security framework as an overlay. I can test security using the tomcat-users.xml file, and then deploy the app unmodified to a server that uses Active Directory for authentication.
Because container-managed security is an external framework that wraps the app instead of getting its sticky little fingers all over the insides of the application itself, the fact that other apps are also running on the system is immaterial to it. I've found, in fact, that container-managed security is especially good for enterprise-level security, since a single authentication data source can be set up to control access instead of forcing security administrators to go through 101 different security systems, one for each app.
Joined: Jun 09, 2009
Thanks Tim, I'll look into that (or try and find someone here who can guide me).