AJAX session keep-alive with expiration detection

This AJAX keepalive script can be used to keep sessions alive on a web server by polling it every minute (using POST requests to avoid caching). The page itself is not reloaded, the requests to the server are happening in the background. A hashed ID based on the server-side session ID is returned and the client-side script checks if it matches the last received session ID.

Embedded in a page, it looks and works like this:

Session status

The system consists of four elements: The client-side HTML that loads the Javascript (example.html), the Javascript itself (keepalive.js), the server-side code for returning the hashed session ID (session.asp) and the hashing algoritm (sha256.asp).

Note that although classic ASP is used in this example for returning a hashed server-side session ID, the server-side part can be implemented on any modern session-aware platform.

example.html (lines needed to be included in the HTML content highlighted):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
<title>Ajax session keep-alive with expiration detection</title>
</head>
<body>

<span id="sessionstatus">Session status</span>
<script type="text/javascript" src="keepalive.js"></script>

</body>
</html>

...Or like this, if the default options need to be tweaked:

<span id="sessionstatus">Session status</span>
<script type="text/javascript">
  kaDebug=false; // Set to true to show the full server response
  kaServerPage='session.asp'; // a page returning the server-side session ID
  kaInterval=60; // keep-alive interval in seconds
  kaOkMessage='session alive';
  kaExpiredMessage='session expired';
  kaErrorMessage='session check error';
  kaStatusElementID='sessionstatus'; // DOM element ID to update with status
</script>
<script type="text/javascript" src="keepalive.js"></script>

keepalive.js: (based on the generic AJAX example)

var kaHttpRequest = false;
var kaOldSessionId = '';
if (typeof kaDebug == 'undefined')
{
  var kaDebug = false;
}
if (typeof kaServerPage == 'undefined')
{
  var kaServerPage = 'session.asp';
}
if (typeof kaInterval == 'undefined')
{
  var kaInterval = 60;
}
if (typeof kaOkMessage == 'undefined')
{
  var kaOkMessage = '<span style="color: #41930a;">Session alive</span>';
}
if (typeof kaExpiredMessage == 'undefined')
{
  var kaExpiredMessage = '<span style="color: #b82c06;">Session expired</span>';
}
if (typeof kaErrorMessage == 'undefined')
{
  var kaErrorMessage = '<span style="color: #b82c06;">Session check error</span>';
}
if (typeof kaStatusElementID == 'undefined')
{
  var kaStatusElementID = 'sessionstatus';
}

kaAjax('POST', kaServerPage, '', kaStatusElementID);
setInterval("kaAjax('POST', kaServerPage, '', kaStatusElementID)", kaInterval * 1000);

function kaAjax(httpRequestMethod, url, parameters, target)
{
  kaHttpRequest = false;
  document.getElementById(target).innerHTML = 'Wait...'
  if (window.XMLHttpRequest)
  { // For Mozilla, Safari, Opera, IE7+
    kaHttpRequest = new XMLHttpRequest();
    if (kaHttpRequest.overrideMimeType)
    {
      kaHttpRequest.overrideMimeType('text/plain');
      //Change MimeType to match the data type of the server response.
      //Examples: "text/xml", "text/html", "text/plain"
    }
  }
  else if (window.ActiveXObject)
  { // For IE6
    try
    {
      kaHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e)
    {
      try
      {
        kaHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e)
      {}
    }
  }
  if (!kaHttpRequest)
  {
    alert('Giving up :( Cannot create an XMLHTTP instance');
    return false;
  }
  kaHttpRequest.onreadystatechange = function() {updateElement(target);};
  if (httpRequestMethod == 'GET')
  {
    var ser = Math.round(Math.random()*1000000); // Anti-caching random number
    kaHttpRequest.open('GET', url + '?' + parameters + '&random=' + ser, true);
    kaHttpRequest.send(null);
  }
  else if (httpRequestMethod == 'POST')
  {
    kaHttpRequest.open('POST', url, true);
    kaHttpRequest.setRequestHeader('Content-Type',
      'application/x-www-form-urlencoded');
    kaHttpRequest.send(parameters);
  }
  else
  {
    alert('Sorry, unsupported HTTP method');
  }
}

function updateElement(target)
{
  if (kaHttpRequest.readyState == 4)
  {
    if (kaDebug == true)
    {
      alert(kaHttpRequest.responseText);
    }
    if (kaHttpRequest.status == 200)
    {
      if (kaOldSessionId == '')
      {
        kaOldSessionId = kaHttpRequest.responseText;
      }
      if (kaHttpRequest.responseText == kaOldSessionId)
      {
        document.getElementById(target).innerHTML = kaOkMessage;
      }
      else
      {
        document.getElementById(target).innerHTML = kaExpiredMessage;
      }
    }
    else
    {
      document.getElementById(target).innerHTML = kaErrorMessage;
    }
  }
}

session.asp:

<%
Option Explicit
%>
<!-- #include file="sha256.asp" -->
<%
' For security, the server-side session ID is salted and
' hashed before being sent to the client
Dim strSalt
strSalt = "rsq8SwDAmEMDkRv5sMvDe3C" ' Just some random data
' The hash is only calculated once and stored in a session variable:
If Session("SaltedSessionID") = "" Then
  Session("SaltedSessionID") = sha256(CStr(Session.SessionID) & strSalt)
End If
Response.Write(Session("SaltedSessionID"))
%>

Note: If you don't care about hashing the session ID, session.asp can be as simple as this one-liner:

<% Response.Write(Session.SessionID) %>

sha256.asp (only needed if the session ID should be hashed):

The SHA256 ASP implementation (sha256.asp) used in this example can be downloaded at http://www.frez.co.uk/vb6.aspx.

Page last updated 2009-08-29 21:19. Some rights reserved (CC by 3.0)

Search

Feeds

RSS 2.0 feed All content
RSS 2.0 feed ajax
RSS 2.0 feed asp
RSS 2.0 feed aspnet
RSS 2.0 feed bicycle
RSS 2.0 feed copenhagen
RSS 2.0 feed databases
RSS 2.0 feed denmark
RSS 2.0 feed diy
RSS 2.0 feed dotnet
RSS 2.0 feed html
RSS 2.0 feed japan
RSS 2.0 feed javascript
RSS 2.0 feed modding
RSS 2.0 feed photography
RSS 2.0 feed utilities
RSS 2.0 feed vbscript