The InactivtyMonitor is used as a preemptive strike against session timeout. Waiting for an error code really ticks off hard-working customers :)
Printable View
The InactivtyMonitor is used as a preemptive strike against session timeout. Waiting for an error code really ticks off hard-working customers :)
I use acegi (now called Spring Security, i think) and it takes care of all the session security needs without having me to write a single line of code. When the user clicks on any link after being idle for x mins, it takes them back to the login screen - haven't figured out how to add a popup with a countdown timer though.
It also provides "remember me" and other advanced options.
Rakesh
I'm having some difficulties securing my web application. Specifically giving me troubles is the back button.
My login page redirects to my "one page" web application. That page has a logout button which also does a redirect, back to the login page.
The problem I'm having is dealing with session timeouts, and logging the user out. Seems that when the user logs out, if they hit the back button I'm not reliably handling what to do next. At the moment when I hit the back button, the page posts to the backend and the backend tries to serve up the full login page (Sending back a slew of html over ajax doesn't work of course).
I think the core of my problem is how to deal with session timeouts and then if the backend wants to say go away or give me a password, how to deal with that. In one case I'm currently telling the user to redirect (either on login or logout). In another case, when the session times out, I'd like to offer the chance to keep the one page web application alive vs. outright kicking them out.
At the moment I think I'm improperly/inconsistently sending back a 401 header. I'm globablly listening to ajax requestcomplete and monitoring it for a 401 header. If it's detected, I mask the screen and popup the login message.
I suspect I need to be sending some kind of token between the server and client on each request, but I'm not sure how to implement that.
Hints?
I mainly use ASP.Net for my server-side code. ASP.Net uses a session-cookie for session persistence. When I perform an inactivity timeout, I tell the server to delete the cookie; and I delete the cookie from the browser. Then, I redirect to the "logged-out screen" (which redirects to the "login screen."
If a user hits the Back button, two things might happen:
1) The browser asks the server for the page. The server sees that the browser doesn't have a cookie (and even if it did, the server no longer has the match for authentication). So, the server redirects to the "login screen."
2) The browser loads the page from the cache and restarts the Ext app. The Ext app will ask the server for data. With no matching cookie, the server sends an error which tells the Ext app to redirect to the "login screen."
That's pretty much what I got going...except I guess I need to do a better job intercepting the response. At the moment the server is trying to redirect, but it's sending the login page back. I suppose I need to look at handling the response from the server better.
I use class observability on the Ext.data.Connection class
http://extjs.com/forum/showthread.php?p=259271
I add a listener for any Ajax requests, and start a timeout the duration of which is the same as the inactivity timerduration on the server. It is reset on every Ajax request.
If the timer fires, it sets location.href to the logout page.
Harley,
Probably I am missing something. If you are polling the server every minute, the session on the server would never timeout, right ? And if the session is active on the server, we do not want to logoff the user from the application. Can you please clarify.
Thanks
If the client app is idle (no click or keydown) for the length of the timeout, I redirect the client app to the logout page. When the logout page request hits the server, the session is killed.
Thanks, Harley. I tried your code but it does not work (no errors). In firebug, I can see the polling to the server (every one minute). But the message box would not show up after the inactivity time (2 minutes).
Harley,
I noticed that sometimes message box shows up after double the amount of inactivity time specified. But sometimes it works fine. Not sure what is causing the issue. I modified your code slightly for my purpose (Not tracking click and keypress events but reset only on any Ajax requests).
Here is my code.
Code:Ext.onReady(function()
{
new InactivityMonitor({
inactivityTimeout: 60000, // (in milliseconds)
messageBoxCountdown: 15, // in seconds
listeners: {
timeout: function() {
window.location = "logout.jsp";
}
},
pollUrl: "web/extJs/desktop/pollSession.jsp",
pollActionParam: "a",
pollAction: "StayAlive"
});
});
Code:var ONESECOND = 1000;
var ONEMINUTE = ONESECOND * 60;
InactivityMonitor = Ext.extend(Ext.util.Observable, {
inactivityTimeout: ONEMINUTE,
pollActionParam: "a",
pollAction: "StayAlive",
pollInterval: ONEMINUTE,
pollUrl: "web/extJs/desktop/pollSession.jsp",
messageBoxConfig: {}, // allows developers to override the appearance of the messageBox
messageBoxCountdown: 10, // how long should the messageBox wait?
constructor: function(config) {
this.addEvents({timeout: true});
Ext.apply(this, config);
InactivityMonitor.superclass.constructor.apply(this, arguments);
if (this.inactivityTimeout >= ONEMINUTE) {
Ext.Ajax.on('beforerequest', this.resetTimeout, this);
}
},
destroy: function() {
this._inactivityTask.cancel();
Ext.TaskMgr.stop(this._countdownTask);
},
resetTimeout: function () {
if (!this._inactivityTask) {
this._inactivityTask = new Ext.util.DelayedTask(this._beginCountdown, this);
}
this._inactivityTask.delay(this.inactivityTimeout);
},
// private stuff
_pollTask: null, // task to poll server
_countdownTask: null, // ONESECOND interval for updating countdown MessageBox
_countdownMessage: null, // countdown MessageBox
_inactivityTask: null, // task to start countdown
_beginCountdown: function () {
var config = Ext.apply({
buttons: {ok: "Keep Working"},
closable: true,
fn: function (btn) {
Ext.TaskMgr.stop(this._countdownTask);
var params = {};
params[this.pollActionParam] = this.pollAction;
Ext.Ajax.request({params: params, url: this.pollUrl});
},
msg: "Your session has been idle for too long. Click the button to keep working.",
progress: true,
scope: this,
title: "Inactivity Warning"
}, this.messageBoxConfig);
if (!this._countdownMessage) {
// only create the MessageBox once
this._countdownMessage = Ext.MessageBox.show(config);
}
var win = this._countdownMessage;
if (!win.isVisible()) {
win.show(config);
}
win.updateProgress(0);
win.seconds = 0;
this._countdownTask = Ext.TaskMgr.start({
run: function () {
win.seconds += 1;
if (win.seconds > this.messageBoxCountdown) {
Ext.TaskMgr.stop(this._countdownTask);
this.fireEvent("timeout", this, win);
} else {
win.updateProgress(win.seconds / this.messageBoxCountdown);
}
},
scope: this,
interval: ONESECOND
});
}
});