Hi, I've got an application where a user has to log in, but if he stays logged in for too long, he is automatically logged out.
In the simplified version of my code here, I've got a timer and a phase listener. The loggedin flag is set when the user logs in, and is set back to false when either he logs out, or the application times out. The timerrunning flag is true when the timer is running, but it's the timedout flag I'm having problems with.
I also have several setters and getters, and the ones for loggedin are only used to determine if a logout button is displayed on some pages.
Basically, when the user logs in, the timer is set for a specific period of time, and for the purposes of my tests I only make it for a few seconds. If the user has not logged in and tries to submit a form, the loggedin and timedout flags are false, and the user is directed to a page indicating that he is not logged in. If the user logs in, but then exceeds the alloted period of time for submitting the form, the loggedin flag has been set back to false and he has been logged out, but the timedout flag is true, so he directed to a different page indicating that his session has timed out. Finally, if he is logged in and submits the form he goes to a success page.
OK, that's all fine an works. The problem is that after setting the timedout flag to true, I want to reset it back to false after he has be directed to the "timeout" page, so that if he tries to submit the form again, he is just told that he is not logged in. I use a phase listener to determine when he visits a particular page.
On examining the output in the log, I notice that once the timeout flag is set to true in the timer, it stays true, even though I set it to false with the action listener. However, if I declare timedout to be a static variable, it seems to work. I would be most grateful for an explanation of this, and if there is a better way of doing all this.
Honestly, this is a fairly cumbersome approach to maintain a logged in user in JSF. And I highly doubt if it is safe. There will only one PhaseListener instance be created during the application's lifetime, which is going to be shared among all sessions and requests.
You normally use the HttpSession to maintain a logged in user. You can set its timeout in the web.xml. The default timeout is 30 minutes. When an user logs in successfully, you set the representing User object (or some other key indicating a logged in user) in the session. When an user logs out, you simply invalidate the session so that the user can continue with a fresh start. Or you just let the session expire which automatically logs out the user. The HttpSession attributes are accessible by ExternalContext#getSessionMap(). The HttpSession itself is available by ExternalContext#getSession(). Alternatively you can also declare a session scoped managed bean, e.g. UserSession, which holds an User property indicating the logged in User.
If you want to intercept on the session timeout in JSF, then you can do it at several ways or combinations of them.
1) Either create a Filter or declare a error-page entry in the web.xml which catches the ViewExpiredException and handles accordingly. This exception will be thrown when the session is expired, but the user continues the POST requests on a page which is left open.
2) Add a meta refresh tag to the HTML head which refreshes the page (and thus also the session) or redirects it to a certain page (the main page or so) when the session is timed out. E.g.
Hope this helps. [ August 26, 2008: Message edited by: Bauke Scholtz ]
It would actually be better (simpler/cleaner) just to use a filter and redirect the request to a timeout processor.
An IDE is no substitute for an Intelligent Developer.
Joined: Dec 12, 2007
OK, many thanks for those replies, and it certainly looks as if it's much better to follow the approach suggested than my ideas.
As I said on previous postings, I'm still pretty new to JSF, and it's taking longer than anticipated to get into it properly. I'm also working on my own, as none of my colleagues here in France know any Java, much less JSF.