I doubt what I am about to write is new. In fact, I drudged up bits and pieces all over the internet from searches and kind of combined a few approaches into my own. So if you are reading this and you say to yourself "Hey, I came up with that" then I thank you. But hopefully someone can gain from this anyway.
One of the few things I despise about AJAX is handling session timeouts. Nothing about it is very graceful and my solution doesn't improve on that. However, it is simple and easy. Basically, the problem is that when a web applications session times out we typically want to redirect the user to the login page. I do this in Stripes using an Interceptor but you can think of that as a Filter or what have you. Basically, something on the server side is checking to see if the session has timed out and redirecting the request appropriately. Something kind of like this
if ( user == null && servletPath.startsWith("/admin"))
{
executionContext.getActionBeanContext().getMessages().add( new LocalizableMessage( "/AdminLogin.action.notLoggedIn" ) );
return new ForwardResolution( AdminLoginActionBean.class );
}
if ( user == null && servletPath.startsWith("/advisor"))
{
executionContext.getActionBeanContext().getMessages().add( new LocalizableMessage( "/AdvisorLogin.action.notLoggedIn" ) );
return new ForwardResolution( AdvisorLoginActionBean.class );
}
In order to get AJAX requests to change the browser location you have to rely on JavaScript, sad to say. What I do is I add 'ajax=' as a parameter to all my AJAX requests. In my Interceptor/Filter I look for this parameter. If I find it and the session has timed out, I change the HttpServletResponse.status to 403
if (map.containsKey("ajax"))
{
ajax = true;
if (session.isNew())
{
logger.debug("###########: SESSION IS NEW");
executionContext.getActionBeanContext().getResponse().setStatus(403);
return executionContext.proceed();
}
}
Using Prototype I set an on403 for all my AJAX requests and call a simple function called sessionTimeout() which does this:
window.location = window.location
What that does is refreshes the page so that the first bit of code I showed above takes over and you actually get to the correct login page.
The only problem with this approach is that if you are doing Ajax.Updater you'll get the login page in whatever DIV element you've specified before the page redirects from the sessionTimeout function. Aside from that it works great.
The only problem with this approach is that if you are doing Ajax.Updater you'll get the login page in whatever DIV element you've specified before the page redirects from the sessionTimeout function. Aside from that it works great.If you examine the request header you can determine what type of request it is, i.e AJAX or Otherwise... in PHP this is:
isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'If AJAX then respond with a header 403 only in which case not content is sent back to render and the on403 handler can do what it does without having the contents of the login page rendered into the div, works for Ajax.Updater as well.
- In my PHP Controller when I detect an expired session I send a HTTP response code of 401
- jQuery's $.ajax({}) has a super awesome statusCode method that can be called when a certain HTTP response code is encountered. Using the $.ajaxSetup({}) to set a global default of:
-
$.ajaxSetup({ statusCode: { 401: function() { // Anything you like here, even window.location.href = "/errors/sessionexpired/" alert('Your session has expired'); } } });
Now whenever I get a 401 response I redirect the user to a page explaining that they need to login again.
What's really nice about this method is that it required very few changes. Once in the controller to set the HTTP response code and then a few lines of JavaScript to setup the defaults which all future AJAX requests would make use of.




