views:

587

answers:

5

I want to build a way to automatically redirect users to Timeout.aspx when their session expires due to inactivity. My application uses forms authentication and relies heavily on update panels within the same aspx page for user interaction, so I don't want to simply redirect after a page-level timer expires. For the same reason, I can't use '<meta http-equiv="refresh"/>'

What I want to do is create a simple ajax web service with a method called IsSessionTimedOut(), that simply returns a boolean. I will use a javascript timer to periodically call the method, and if it returns true, then redirect to Timeout.aspx. However, I don't want calling this method to reset the session timeout timer, or the session would never time out because of the service call. Is there a clean way to avoid this catch-22? Hopefully there is an easy solution that has so far eluded me.

A: 

Is it really critical that the timeout happen when the server-side session expires?

If you just want to force users to refresh their sessions or time them out, I would use window.setTimeout() to redirect to Timeout.aspx after a set time. The codebehind of Timeout.aspx can call Session.Abort() to kill the session, which will force the user to log back in if they want to continue.

I think this method will actually be more accurate and reliable than the Session timeout, which (in my experience) tends to vary depending on the server load and other factors.

Dave Swersky
Good solution, but I think it breaks down if the user has multiple tabs or windows open. A background tab could end up causing an unexpected logout to occur.
Mercury821
A: 

I think that if you enable session state for your web service, and then set the SessionStateBehavior to read only in your global.asax if the web service is being hit, you should be good. You'll need to do this early in the lifecycle.

http://msdn.microsoft.com/en-us/library/system.web.httpcontext.setsessionstatebehavior(v=VS.100).aspx

bryanjonker
This is a good thought... unfortunately it only seems to be available in .Net 4.0, and I am targeting 3.5.
Mercury821
A: 

I think you are going about this the wrong way... If you absolutely can't use a simple meta-refresh (by far the easiest way to handle this) then just handle the cases where your AJAX methods return values that indicate your session has timed out. Why do you need an extra mechanism just to do this? I'm not that familiar with the UpdatePanel... but if the update fails when your session is expired, surely you can send back some "hey pardner, you need to log in again" message?

Bryan
Handling the ajax return values wouldn't be enough, because I need the browser to automatically redirect to Timeout.aspx after a period of inactivity, such as when the user gets up and walks away from the computer. In that case, there wouldn't be any ajax calls to the server.
Mercury821
A: 

This is the best solution I've come up with so far, but I'm open to something better. Basically, I have a 15-minute javascript timer that is reset with every async postback. The disadvantage of this approach is that a second tab or window open in the background would cause the session to end, even if the user is actively using the application in another browser window.

Something similar to this lives on my master page. The last line of javascript adds my reset function to be triggered when any update panel refreshes:

        <asp:ScriptManager ID="ScriptManager1" runat="server" ScriptMode="Release" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError">
        <Scripts >
            <asp:ScriptReference Path="~/scripts/jquery/jquery-1.3.2.min.js" />
        </Scripts>
        </asp:ScriptManager>

        <script type="text/javascript">

        var redirectTimer = setTimeout('redirectToLogout()', 900000);

        function redirectToLogout() {
            window.location = "/logout.aspx";
        }

        function ResetTimeoutTimer() {
            clearTimeout(redirectTimer);
            redirectTimer = setTimeout('redirectToLogout()', 900000);
        }


        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(ResetTimeoutTimer);

       </script>
Mercury821
+1  A: 

the crux of the problem is that in AJAX apps, to provide a robust user experience you must clutter your client script with reams of code checking the status of every call and determining if a failure is due to a stale session/ticket. With a proactive approach your client script can be dramatically simplified while at the same time providing a much better user experience.

I have built a solution for this problem specifically.

It allows interactive session and forms ticket lifetime auditing without bumping the session or ticket.

Multiple browsers/tabs are no problem.

Forget the sunscreen; Remember: When doing Ajax, be proactive - You should abandon a session, a session should not abandon you ;-)

AsynchronousSessionAuditor 1.0

Sky Sanders
This looks very promising. I never thought about introducing an HttpModule into the mix. Thanks!
Mercury821
@Mercury - you are very welcome. I am glad that it can be of use.
Sky Sanders