Cookies are useful tools for maintaining information about the users on your Web site. For example, when you create a shopping cart for an online e-commerce application, you can store your user’s product selections in a cookie. The contents of the cookie can be viewed no matter on which page they end up. Cookies can also be useful for storing user preferences and authentication data.
All about cookies
For more information on cookies, check out this comprehensive article.
The HTTP protocol and data persistence
Why do cookies exist in the first place? Netscape developed the cookie mechanism to address a few shortcomings in the HyperText Transfer Protocol (HTTP) specifications.
HTTP is stateless by nature, which means that the data contained on one page will not be stored when you navigate to the next page. For example, when you enter a URL in your browser, it will request the corresponding page from the Web server. Once the page has been served, all communications will cease until another request is made.
Here is the inherent problem with HTTP: There’s no built-in mechanism to persist data in between page requests. If you fill in a form online and forget to click the Submit button, everything you typed in will be lost. There is nowhere else for the data to go.
Sessions states were developed as a way of tracking every unique user that visits your Web site. Sessions provide detailed user information for your server logs. They also allow you to programmatically monitor and control individual users on your Web site.
Here is how sessions work: The server generates a unique ID for each user (called a session identifier). This identifier is usually placed in a cookie in the client browser. When your user accesses the Web site, the server will retrieve the cookie and then make note of the user’s session identifier.
Don’t rely only on cookies
You shouldn’t rely strictly on cookies for functionality. For example, what happens if your Web application is viewed through a wireless device that doesn’t support cookies or is viewed through a pre-HTML 2.0 or text-based browser? Another possibility is that your audience may be using cookie-blocking technology to protect their privacy. To reach the widest audience possible, developers should take these scenarios into consideration when building any cookie-based Web application.
To deal with a situation where cookies aren’t available, you must build a custom session handler to transfer session information back and forth between the browser and Web server. This article outlines strategies that let you add data persistence to your applications without using cookies.
Here are four solutions to simulate cookie-like functionality in your applications. We will look at using query strings, cookieless behavior in ASP.NET, hidden forms, and parent frames. Each approach has its unique applications and challenges.
Query string approach
Using the query string approach, the cookie value is stored in the URL and can be retrieved by both the server and the browser. Here is an example of a session identifier embedded in a Java Server Pages URL:
Exposing the session ID is generally not a good idea from a security standpoint. If a hacker can obtain your ID and you are logged in, the hacker may be able to hijack your session. More information about this vulnerability can be found in this Builder.com article on ASP.NET apps.
A solution to this problem is creating a hash value that incorporates the session identifier and information specific to the client. A hash is a unique value or checksum that is generated from a text string. Since hashes are generated using encryption algorithms, it is highly unlikely that other combination of characters will create the same hash.
If we take the session identifier listed above and the IP address of the user and combine them in a string, the result would be:
If you hash this string using an MD5 encryption, the result would look like this:
To authenticate the user, all you’d need to do is retrieve the user’s IP address and the session identifier. Then you would generate a hash and compare it to the hash stored in a database. If they don’t match, either it is a new session or someone is trying to hijack another user’s session (because the session ID matches but not the IP address, or vice versa). Otherwise, the user is authenticated.
Here is some server-side code in ASP to retrieve the IP address and the session ID for a user:
IPAddress= Request.ServerVariables (“REMOTE_ADDR”)
SessionID = Request.QueryString (“sessionid” )
The .NET Framework’s System.Security.Cryptography base library provides a rich set of tools for handling the encryption and decryption process.
ASP.NET and cookieless sessions
The ASPSESSIONID variable is used to track users on an ASP-driven site. Cookies are typically used to assign the session ID to individual users. Here is an example of a typical ASP session cookie:
Set-Cookie: ASPSESSIONID=ANSJDHUMHSHGJSYU; path=/Webapp
For cookieless transactions in IIS4, you can use an ISAPI filter called Cookie Munger (ckymunge.dll) available in the Windows 2000 Server Resource Kit. However, this filter can cause performance problems on your server in high-traffic situations. You can view more information about the filter here.
ASP.NET has a built-in fallback mechanism to maintain cookieless sessions. IIS5 will do all the work of tracking the session information coming to and from the browser by automatically embedding the session identifier in all the relative links on your Web site. Here is an example of an ASP.NET URL implementing this feature:
The disadvantage of this approach is that if the user removes the session information in the URL, the session tracking will likely be lost. To deploy cookieless sessions in your ASP.NET application, all you need to do is reconfigure the cookieless variable in the config.Web file:
��� <sessionstatecookieless=”true” />
Hidden form approach
The goal with the hidden form approach is to post a hidden value to the server every time a user navigates to a new page on your Web site. To make this work, every page on your site has to contain a form and an embedded hidden form field that looks something like this:
<input type=”hidden” name=”sessionid” value=”F0DS2AAGGDJBB5FSFJ32DFV”>
The disadvantage of this approach is that the session information has to be passed from the server to each subsequent page for persistence to occur. The user has to use the navigation provided on the Web site.
Using a PC-based Web browser, it is easy for users to type in a new URL in the location bar. If they do this, the result is that the current session will be lost and a new one will be created when they return to the Web site. Since sessions are constantly generated and tracked, this approach may cause server performance problems on high-traffic sites. Since it’s likely that the user may obtain multiple session identifiers during each Web site visit, you can’t guarantee effective data persistence on a regular Web site using this method.
On the upside, wireless Web sites would benefit from the hidden form field approach. Most cell phones support basic HTML constructs such as forms. And users tend to use the navigation provided on a mobile Web page to move around. Compared to a standard Web browser, it takes a little more effort to key in a URL on a cell phone keypad than to click a form button.
Parent frame approach
<frameset rows=”100%,*” frameborder=”0″ border=”0″ framespacing=”0″>
��� <frame name=”main” src=”contentpage.asp” frameborder=”0″ border=”0″>
��� <frame name=”session” src=”sessionid.asp” frameborder=”0″ border=”0″>
In the visible frame, we can assign to sessionid the value of the sessionIdentifier variable located in the hidden frame:
varsessionid = parent.session.sessionIdentifier;
This approach would work well for a Web site that uses frames, but it would be inaccessible to most mobile devices and older browsers. Developers are typically discouraged from using frames because it is generally acknowledged that frames decrease the usability of a Web site. For more details, check out this article by usability guru Jakob Nielsen.
The solutions we’ve looked at here cover conventional HTML-based technologies, but there are other ways of maintaining a session that extends beyond normal browser functionality. Here are a couple of these approaches.
Using SOAP headers, it is possible to send and receive data, including session data. Edmond Woychowsky outlines some of the possibilities in his article “XMLHTTP ActiveX objects offer alternative to accessing ASP session variables.”
You can use Java applets to relay information back and forth between the server and the client without any browser intervention. Applets have no explicit support (or classes) for maintaining persistent states in the browser. However, applets can maintain a persistent state, create files, and read files on the server side. For the details, check the documentation for the Java2 Standard Edition Networking (java.net) package.
Persistence can pay off
These are just a few ideas that incorporate existing technologies to provide data persistence. Depending on your platform and development resources, you can implement whichever strategies work best for your site.