State and session tracking with Java servlets Part 2: Securing data
By default, the cookies created by Java servlets will expire when the browser exits. Often, however, it's handy to have this data persist for days, weeks or even months later. For example, a cookie that tracks user preferences should remain until the next visit. We can manually specify an expiration date, using the
Cookie.setMaxAge( int )
// Store color preference for one year
Cookie cookie = new Cookie ("color", "blue");
cookie.setMaxAge ( 60 * 60 * 24 * 365 );
// Add cookie to response
Security implications of storing state information in cookies
When dealing with mundane details, like a counter, it's perfectly safe to store data in cookies. However, if the state information contains unique identifiers, such as a User-ID, then it can represent a strong security risk. If that User-ID authorizes access to a particular resource, then anyone who runs the Web browser can gain access. Under ideal situations, only a single user has access to a particular machine, but in shared environments (such as Internet cafe terminals, or offices), other people can access the browser and masquerade as a particular user.
This poses a potential security risk but one that can be guarded against. As mentioned earlier, it is possible to specify an expiration date for the cookie. Once the expiration date is reached, the cookie is discarded from the browser. By default, cookies created by Java servlets will expire once the browser exits. However, in a shared environment where browsers remain open, this represents too great a security risk. The solution is to specify a very short expiration date (for example, in two minutes) and to periodically refresh the cookie as new requests come in.
// Create a cookie containing the userID
Cookie cookie = new Cookie ("userID", getUserID() );
// Specify a three minute timeout
cookie.setMaxAge ( 180 );
// Send back to the browser
For added security, it is also important to provide a "logout" function. This allows users to close their account, so that no further access can be gained without specifying a password or being authenticated. This is important as it is possible for another user to come along before the cookie has expired (though forgetful users still have the safeguard of a timeout). To void a cookie, simply specify a maximum age of zero.
// Void the cookie and send it back to the user
For simple tasks, cookies are a useful mechanism for storing simple state data. To store data securely, however, involves extra effort. A better mechanism is session management.
State versus session management
Session management allows a "virtual connection" to be established between browser and servlet. Rather than storing state information in cookies, hidden fields, or hyperlinks, a session identifier is assigned to each user. This identifier is then used to track individual requests and match them to a session. However, sessions persist for a limited period of time and are associated with a single user. No state information needs to be sent across the network such information can be stored within the servlet and looked up as required.
This approach offers two big advantages over stored state variables in forms, hyperlinks, or cookies:
- simplicity for the developer
- less network utilization, as state data is not sent repeatedly.
The session approach is simpler for the developer, as there is no need to constantly refresh cookies or to write code to expire them. As state information isn't sent to the browser and then echoed back to the server, less bandwidth is consumed. The Servlet API provides support for session-tracking, in the form of the
Overview of HttpSession
Session-tracking is made extremely easy with the
class. Developers don't need to worry about generating a unique session ID or storing it. For browsers that support cookies, a temporary identifier will be issued, and then echoed back by the browser every time a request is made. If cookies are not supported, then a servlet can use the technique of URL re-writing to encode a session identifier in every hyperlink. For most situations, however, cookies are sufficient for storing a session identifier.
Creating an HttpSession
Creating a new session is relatively straightforward. The
will return the current session. The
parameter to this method specifies whether a new session should be created if one does not already exist. So to create a new session, or obtain an existing one, the code remains the same.
// Get the session for this client
HttpSession session = request.getSession(true);
Storing and retrieving data from a HttpSession
Once a session has been established, state data can then be added or removed. Like cookies, it is represented by a key-value pair. A single key maps to a single object but this object can be an array if storing multiple values is necessary.
// Store userID in current session
session.putValue ("userID", request.getParameter("userid") );
Retrieving values is almost as easy. Using a string key, the contents of state data can be returned using the
method. However, the return type for this method is Object, so it is often necessary to cast to a specific class.
// Return the list of items in shopping trolley
Vector vec = (Vector) session.getValue("list");
// Check to see if value exists
if (vec != null)
// Code to process contents would go here ...
Other issues with HttpSession
By default, session-tracking is accomplished using cookies. This process is transparent for the developer no extra code to store and retrieve cookies need be written. However, if cookies are disabled or not supported, every hyperlink must be encoded to include a session identifier. Without this, the session becomes lost. The
method is used for this purpose. However, the details of this encoding is specific to each web-server or servlet engine, and not every server supports this feature. This feature should be viewed as a last resort - it is preferable for cookies to be used instead. If URL-rewriting is supported though, it will allow older browsers without cookie support to access the servlet. As an example, to encode a reference to a servlet, we could use the following code:
// HttpServletResponse.encodeUrl adds session data automatically
response.encodeUrl ( "/servlets/MyServlet" );
Developers should also be mindful of the fact that sessions are for storing temporary data, not for data that lasts for a long period of time. Sessions will not persist once the browser or servlet terminates, so any important data should be saved to disk or to a database. To allow easy retrieval of data at a later date, a username/password could be established, and a session created once the identity of the user is authenticated. Any changes to state data would be saved once the session closes, and accessed again at a future point in time.
Putting session-tracking to work
To demonstrate session-tracking with the
class, I've written a simple application that records user color preferences. A new session is created immediately, and state data for the background and foreground page colors is added to the session. Changes can be made to state data, and these changes are retrieved each time a page request is made. A form is provided, to allow customization of state data. In addition, a hyperlink is also provided, to demonstrate that even when no CGI parameters are specified, state data is being retrieved. Figure 1 shows the servlet in action, when new values have been specified as CGI parameters. If cookies are enabled, or URL-rewriting is supported, clicking on the URL retains customized color preferences.
NB: To test URL-rewriting, cookie support must be disabled, and the servlet engine must be capable of supporting it.Listing 1: HttpSessionExample.java (See page 2)
Figure 1. Demonstration of session-tracking using HttpSession.
Whether you choose to create your own session-tracking mechanism using cookies or to use the
class, the Servlet API makes it easy to maintain state information across HTTP connections. For storing simple state information, cookies represent an excellent choice. However, for servlets where security is a concern, care must be taken to specify an adequate timeout value. For larger-scale projects, developers may also benefit from the existing session-tracking features provided by the Servlet API.
About the author
David Reilly is a software engineer and freelance technical writer living in Australia. A Sun Certified Java 1.1 Programmer, his research interests include the Java programming language and networking & distributed systems. He can be reached via e-mail at firstname.lastname@example.org.
Page 1 of 2