Track Client Windows - Browser Session Identifier

A large number of web application developers had expressed the desire to track and identify client browser windows on the server side.
We have also run into this problem recently and after several attempts, I think I found the solution to this problem finally.
 
Some of the requirements are below.
1. Assign a unique name to each client window
2. Use the server session to keep track of data saved to the session separately by each of the windows
3. Automatically close a server session when the last open window is closed on the browser
 
The solution involves using the following.
1. Session Cookies (We will call these cookies as WinID Cookie)
2. Client side Cookie Management Scripts
    2.1 OnLoadCookieScript
    2.2 OnBeforeUnloadCookieScript
3. Server Side Cookie Inspector script
4. Server Side Session Management script.
5. WindowSessionIdentifier -> hidden field on every page.
 
Approach
 
On the server side
1. Inspect the request to check if it is coming from a known session window. See the section below for "How to Identify" if it is from a known window.
The web browser always sends cookies issued by the domain path back to the server even if the request is a first request.
In this case, since it will not have any WinID cookies, the server cannot identify a current session and hence will create a new guid. 
    a.    Create new guid,
    b.    Use the new guid to create a new cookie which has the name as "WinID__<New GUID Value>".
    c    Set the value of the cookie to 0
 
On the client side.
1. On every page load, set all window_session_id cookies to 0.
2. Before Page unload event (window.onbeforeunload)set the  window_sesison_id_cookie representing the current window to 1 
    a.  Find the cookie that has the name equal to the value of the hidden field.
    b.  Set the value of this cookie to 1.
 
 
"How to Identify" if it is from a known window.
Since the webserver receives all of the cookies from the browser at all times, it should identify the window sending the request using the cookie value.
The Pre Unload Java Script makes sure that all WinID cookies expcept that corresponding the current window will have a value of 0.
 
So, find the cookie that has name like "WinID__" and has a value of 1. The remainder of the cookie name gives us the value that identifies the window.
If we can find a cookie that has value 1 in the cookies coming with the request, it is coming from a known session.
 
While this approach may not work for every situation for you, it gives you a good starting point to start identifying the windows uniquely on the server side.
This is also a first step in maintaining session segments separately so all expensive data that is browser instance specific can be stored on the server side itself.
 
 
CODE SAMPLE
 
 
 
 

<

script language="javascript" type="text/javascript">

window.onbeforeunload = PreUnloadJavaScript;

window.onload = OnLoadClearCookies;

function OnLoadClearCookies() { var parts = document.cookie.split(';'); var pLen = document.cookie.split(';').length; for (var i = 0; i < pLen; i++) { var ck = parts[i].split("="); if (ck[0].match("winID__") != null) {

setCookie(ck[0], 0);

}

}

}

function PreUnloadJavaScript() { var idLabel = document.getElementById("<%= uxWinID.ClientID %>"); var cookieName = "winID__" + idLabel.innerHTML; var allCookies = get_cookies_array(); var winIDCookie = getCookie(cookieName);

setCookie(cookieName, 1, 1);

var parts = document.cookie.split(';'); var pLen = document.cookie.split(';').length;

cookieName=cookieName.replace(

" ", ""); for (var i = 0; i < pLen; i++) { var ck = parts[i].split("="); var itemName = ck[0].replace(" ", ""); if (itemName == cookieName) { /// Do you magic here

setCookie(cookieName, 1);

}

else {

setCookie(ck[0], 0);

}

}

}

function setCookie(c_name, value, expiredays) {

var exdate = new Date();

exdate.setDate(exdate.getDate() + expiredays);

document.cookie = c_name + "=" + escape(value) +

((expiredays == null) ? "" : ";expires=" + exdate.toUTCString());

}

function getCookie(c_name) {

if (document.cookie.length > 0) {

c_start = document.cookie.indexOf(c_name + "=");

if (c_start != -1) {

c_start = c_start + c_name.length + 1;

c_end = document.cookie.indexOf(";", c_start);

if (c_end == -1) c_end = document.cookie.length;

return unescape(document.cookie.substring(c_start, c_end));

}

}

return "";

}

 
 

ASP.NET CODE BEHIND

 

 

protected void Page_Load(object sender, EventArgs e)

{

List<HttpCookie> allCookies = new List<HttpCookie>(); foreach (string key in Request.Cookies.Keys)

{

allCookies.Add(Request.Cookies[key]);

}

List<HttpCookie> sessionCookies = allCookies.Where(c => c.Name.Contains("winID__") && c.Name != "winID__").ToList(); HttpCookie currentSession = sessionCookies.FirstOrDefault(c => c.Value == "1"); int expTime = 1; foreach (HttpCookie c in sessionCookies)

{

if (Response.Cookies[c.Name] != null)

{

Response.Cookies[c.Name].Value =

"0";

Response.Cookies[c.Name].Expires =

DateTime.Now.AddHours(expTime);

}

else

{

HttpCookie ck = new HttpCookie(c.Name, "0");

ck.Expires =

DateTime.Now.AddHours(expTime);

Response.Cookies.Add(ck);

}

}

if (currentSession == null)

{

uxWinID.Text =

Guid.NewGuid().ToString(); string cookieName = "winID__" + uxWinID.Text; HttpCookie ck = new HttpCookie(cookieName, "0");

ck.Expires =

DateTime.Now.AddHours(2);

Response.Cookies.Add(ck);

}

else

{

uxWinID.Text = currentSession.Name.Replace(

"winID__","").Trim();

}

}

 

Comments