Search code examples
asp-classicvbscript

Classic ASP / End of session redirect


I want to automatically redirect to the login page when the users session has expired.

I have been using the following code in an include file that sits at the top of every page in my application:

Session.Timeout = 60
Response.AddHeader "Refresh", CStr(CInt(Session.Timeout + 1) * 60)
Response.AddHeader "cache-control", "private"
Response.AddHeader "Pragma","No-Cache"
Response.Buffer = True
Response.Expires = 0
Response.ExpiresAbsolute = 0

If Session("accountID") = "" Then
    Response.Redirect("http://www.mydomain.com/")
End If

This works but there is very slight bug. Every now and then the page will refresh even though the session is still alive and it seems that it refreshes before the 60 minutes is up!

Can anybody see what the problem is or can you suggest a different method?


Solution

  • Seeing as though you have to do this client side I'd favour JavaScript/jQuery and AJAX over that method. Here's an example of how to do it.

    Essentially you just set-up an AJAX call to poll a script which returns (in JSON format) whether the user is logged in or not; if they're not then you can transfer them to another page.

    The benefits to this method are that you can poll whenever you want; e.g. every 10 seconds to see whether the user is still logged in rather than having to wait a full hour. It also means that you don't need to state the session time-out figure in your code and so you can leave that to be determined in IIS. Also if the user logged off elsewhere in your system, or your application pool recycled and their session was reset this would detect it fairly quickly.

    I notice from your profile that you're a Paparazzi photographer. I'd consider this the DSLR method and the response header method the cheap phone camera method :o.

    To build your session checker page create a file called session.asp (in the same folder as your other files to make life simpler). In it put:

    <%
    Response.ContentType = "application/json"
    If Session("LoggedOn") Then
       Response.Write "{""loggedOn"": true}"
    Else
       Response.Write "{""loggedOn"": false}"
    End If
    %>
    

    If the user is logged in it returns {"loggedOn": true}, if they're not {"loggedOn": false}. This is what we'll use on your other page to poll if they're logged in by calling this page periodically and reading the response.

    Now onto your pages which originally had your Response.AddHeader code in. Remove all of your code as this replaces it.

    First make sure you have a reference to jQuery on your pages:

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    

    And then put under this line the following:

    <script type="text/javascript">
        $(document).ready(function() {
    
            var checkLoggedOn = function() {
                $.getJSON('session.asp', function(data) {
                    if (!data.loggedOn)
                        window.location.replace("http://stackoverflow.com");
                });
            };
    
            // Call checkLoggedOn every x milliseconds
            setInterval(checkLoggedOn, 30000);
        });
    </script>
    

    All being well, it should work. I set the above to poll every 30 seconds (30000) but you could increase/decrease this to whatever you wanted.

    Note I borrowed large parts of the code above from https://stackoverflow.com/a/4928564/171703 and https://stackoverflow.com/a/2709160/171703.


    Update:

    From the comments below, if you want the user's session to expire after the timeout figure (whether they are keeping their session alive or not) then you could do this.

    When the user is logged in, set a new session variable for LoginExpiration:

    Session("LoginExpiration") = DateAdd("n", Session.TimeOut, Now())
    

    This takes the current time and adds to it the session timeout figure - giving you the time when their session should be destroyed.

    If you now modify your session.asp to the following it takes the LoginExpiration figure and returns that the user is not logged in the event of:

    1. The users session has timed out (IIS application pool reset, or they clicked logoff etc)
    2. The current date/time is greater than the set LoginExpiration time

    Which is:

    <%
    Response.ContentType = "application/json"
    
    LoggedOn = "false"
    LoginExpiration = Session("LoginExpiration")
    DateNow = Now()
    
    If IsDate(LoginExpiration) Then
        If DateNow < LoginExpiration Then
            LoggedOn = "true"
        End If
    End If
    
    Response.Write "{"
        Response.Write """loggedOn"": " & LoggedOn & ", "
        Response.Write """loginExpiration"": """ & LoginExpiration & """"
    Response.Write "}"
    %>
    

    I've put the loginExpiration figure into the JSON response so you could work with it client side if you wanted too.