Unique Session ID between tabs
Managing ASP.Net application state is one of those tasks that is easy to do, but hard to master. There are numerous ways of maintaining state within an ASP.Net 2.0 application: using the Session object, the Application Object, using the View State, Hidden fields, cookies, etc etc etc. There are many ways of doing it, each of which has various pros and cons depending on the situation.
When you use the Session object, it is generally taken for granted that the information that is stored will only be available for that particular session. Not true. Session state is easily shared, specifically, if you attempt to create a new session between two tabs within the same browser process. The reason for this is that, generally, session ID's are generated by using a cookie called "ASP.Net_SessionId" (default name of the cookie). Which immediately points out why a browser with multiple tabs (or even multiple instances of the browser) share the session information. If the cookie isn't expired, the browser will use the same cookie for every request to the page. IIS will then assume that it's the same session and provide access to the session values previously stored for that ID.
So that's the kicker, then. How do we get around it though? What if you have a situation where you need a unique session for every tab, every window, every instance of your browser? Let's investigate what happens with the cookie between requests.
1: protected void Page_Init(object sender, EventArgs e)
2: {
3: Random rand = new Random();
4: Session["Value"] = Session["Value"] ?? rand.Next().ToString();
5: this.ltrlSessionID.Text = Session.SessionID;
6: this.ltrlSessionValue.Text = (string)Session["Value"];
7: }
This sets the Session["Value"] to a random number if it doesn't already exist, it then prints out the current Session ID and session value in two literals (placed on a form). If you run this code you'll get something similar to the following:
And the same thing happens with multiple windows:
If we run the same application in Firefox we see that we get a different Session created, but as soon as we create a new tab or window the sessions in firefox are the same again:
The reason? The cookie that is used to generate a session ID:
As we can see, the session ID of the firefox instances is going to be "pc0omg35wzvocg55rqmjn2ez" until the session expires.
Is there anything we can do to get around this? What happens when we disable cookies in the browser? Well, if we disable cookies we get a different session ID for every tab. Perfect! NO!!! As soon as we disable cookies, not only do we get a unique session ID for each tab or instance, but we get a unique session ID for each request to the page. This means no session state is passed between the pages of our application. Not very useful. Lets try setting the sessionState of our application to Cookieless. If we do that, the session ID is generated and stored in the URL of the application. That works, but you have to be careful with referencing absolute URL's in your application then. Using ResolveClientUrl(string) works around this problem though. So now we have a solution:
Solution:
Set your ASP.Net application to use Cookieless sessionState.
Here we can see that the session ID is stored as part of the URL, creating a new tab or window creates a new session ID but the original window maintains it's session ID. Obviously there are advantages and disadvantages to this approach:
Disavantages:
- Session Hijacking - A hacker could very easily impersonate your session by copying the session ID from the address bar
- You can no longer have fully qualified links within your ASP.Net application - You have to use ApplyAppPathModifier to get a correct URL for your link (<a href='<%= Response.ApplyAppPathModifier("/test/page.aspx")%>'>link</a>)
Advantages:
- Cookie injection is prevented
- Your application will work even if the user has disabled cookies
So there you have it, get around using the same session in multiple tabs if you have to, but be aware of the implications of doing so.