Download as pdf or txt
Download as pdf or txt
You are on page 1of 20

The JSP Files (part 6): State Of Grace

By Vikram Vaswani and Harish Kamath

This article copyright Melonfire 2000−2002. All rights reserved.


The JSP Files (part 6): State Of Grace

Table of Contents
A Perfect State.....................................................................................................................................................1

Wasted, Dude!.....................................................................................................................................................2

A Few Ground Rules..........................................................................................................................................3

Learning To Write..............................................................................................................................................4

...And Read..........................................................................................................................................................8

What's In A Name?...........................................................................................................................................10

Plan B.................................................................................................................................................................13

Session Dissection..............................................................................................................................................14

Access Denied....................................................................................................................................................16

i
A Perfect State
Over the past few weeks, you've learned a great deal about the various control structures and objects available
in JSP. You've see how to retrieve information posted in an online form, and connect your JSP document to a
database for dynamic content generation.

This week in The JSP Files, we're going to tackle yet another very interesting topic − the problem of
maintaining "state" on a Web site. We'll be looking at two common solutions to this problem − cookies and
server−based sessions − and using simple examples to illustrate the JSP constructs available to help you
identify and track client requests on your Web site.

You'll also learn more than you want to know about what exactly "maintaining state" actually means, the
advantages and disadvantages of each of the approaches just described...and, if we're doing our job right, get a
laugh or two out of the whole exercise.

A Perfect State 1
Wasted, Dude!
It's one of the things geeks say to each other when they want to impress the young women in earshot: "HTTP
is a stateless protocol, and the Internet is a stateless development environment". In simple language, all this
means is that the HyperText Transfer Protocol, which is the backbone of the Web, is unable to retain a
memory of the identity of each client that connects to a Web site, and therefore treats each request for a Web
page as a unique and independent connection, with no relationship whatsoever to the connections that
preceded it − very similar to the behaviour of some of today's more adventurous teenagers, who get drunk
every night, wake up the next morning with no memory at all of what happened, and go out again in the
evening to do the same thing all over again...

Now, so long as you're aimlessly surfing from one site to another, this works without a problem. But what if
you've decided to buy a few discs from CDNow.com? In a "stateless environment", it would be very difficult
to keep track of all the items you've shortlisted for purchase, as the stateless nature of the HTTP protocol
would make it impossible to keep track of the items selected.

Consequently, what is required is a method that makes it possible to "maintain state", something that allows
client connections to be tracked and connection−specific data to be maintained. And thus came about
"cookies", which allowed Web sites to store client−specific information in a file on the client system, and
access the information in the file whenever required. So, in the shopping cart example above, the items
selected would be added to the cookie, and would be retrieved and presented to the customer in a consolidated
list during the billing process.

Why are they called "cookies"? The PR agency handling the account was obviously asleep at the wheel.

Wasted, Dude! 2
A Few Ground Rules
Since cookies are used to record information about your activities on a particular site, they can only be read by
the site that created them. For example, Yahoo and Deja.com store your username in a cookie on your hard
drive and use this information to automatically fill in log−in forms the next time you visit their Web sites. It's
kinda like going to a chic restaurant, and having the maitre'd call you by name (something which hasn't
happened to us of late!)

Before getting into the nitty−gritty of cookie technology, a few ground rules are in order:

1. A single domain cannot set more than twenty cookies. A single cookie cannot exceed 4 KB in size. The
maximum number of cookies that may be set is 300.

2. The most common method of transmitting a cookie to a client is via the "Set−Cookie" HTTP header.

3. A cookie usually possesses five types of attributes.

The first of these is a NAME=VALUE pair, used to store information such as a username, email address or
credit−card number. The NAME is a string used to identify the cookie, while the VALUE is the data to be
stored in the cookie. For example,

clarkkent=superman

The EXPIRES attribute defines the date on which the cookie is automatically removed from the system. The
date must be in the format "weekday, dd−mon−yy hh:mm:ss GMT". For example,

expires="Sun, 31−Dec−2030 17:51:06 GMT"

Cookies without a specifically defined expiry date remain active for so long as the browser remains open, and
are destroyed once the browser is closed. You can delete an existing cookie be setting this attribute to a date in
the past.

The PATH attribute is used to set the top−level directory on the Web server from which cookies can be
accessed. In most cases, this is set to

path=/

to ensure that the cookie can be accessed by each and every document on the server.

The DOMAIN attribute is used to specify the domain which the cookie is linked to, and the SECURE attribute
indicates that a cookie should only be set if there exists a secure protocol between the browser and the server.

4. Of all the five attributes, the first is the only one that is not optional.

5. Every good browser offers users the option to disable cookies. If a user decides to exercise his or her right
to do so, your cookies will not be stored, and any attempt to access them will fail. Users who do this are
usually career criminals or tax evaders.

A Few Ground Rules 3


Learning To Write...
Now, there are innumerable ways to go about creating and reading cookies on a client browser − you can use
Javascript, you can use PHP, you can use any of the wonderful programming languages out there. However,
our concern here is with JSP − so let's take a look at an example which demonstrates how to read and write a
cookie.

This is a simple hit counter which creates a cookie the first time the user visits the Web page, and then
increments the counter on each subsequent visit.

<%
// counter.jsp

// declare some variables


Cookie cookieCounter = null;

// the cookie you want


String cookieName = "counter";
int cookieFound = 0;

// a few more useful variables


String tempString;
int count=0;

// get an array of all cookies available on client


Cookie[] cookies = request.getCookies();

// iterate through array looking for your cookie


for(int i=0; i<cookies.length; i++)
{
cookieCounter = cookies[i];
if (cookieName.equals(cookieCounter.getName()))
{
cookieFound = 1;
break;
}

// if found
if(cookieFound == 1)
{

// get the counter value as string


tempString = cookieCounter.getValue();

Learning To Write... 4
The JSP Files (part 6): State Of Grace

// convert it to a number
count = Integer.parseInt(tempString);

// increment it
count++;

// back to a string
tempString = Integer.toString(count);

// store it in the cookie for future use


cookieCounter.setValue(tempString);

// set some other attributes


cookieCounter.setMaxAge(300);
cookieCounter.setPath("/");

// send cookie to client


response.addCookie(cookieCounter);
}
// if not found
else
{
// create a new cookie with counter 0
Cookie alpha = null;
alpha = new Cookie("counter", "0");
alpha.setMaxAge(300);
alpha.setPath("/");
response.addCookie(alpha);
}
%>

<html>
<head>
<basefont face="Arial">
</head>

<body>

<%
// display appropriate message
if (count > 0)
{
out.println("You have visited this page " + count + " time(s)!
Don't you
have anything else to do, you bum?! ");
}
else
{

Learning To Write... 5
The JSP Files (part 6): State Of Grace
out.println("Welcome, stranger!");
}
%>

</body>
</html>

Sure, it looks a little complicated − but it won't once we break it down for you.

The first thing you need to know is how to create a cookie on the client − this is accomplished with the
following code:

<%
Cookie alpha = null;
alpha = new Cookie("counter", "0");
alpha.setMaxAge(300);
alpha.setPath("/");
response.addCookie(alpha);
%>

The first two lines create a new instance of a Cookie object − "alpha". The cookie variable "counter" is then
initialized and set to the string "0". Next, the setMaxAge() and setPath() methods of the Cookie object are
used to set the expiry date (in seconds) and the cookie's availability, respectively. Finally, a call to the
Response object's addCookie() method takes care of actually transmitting the cookie to the client.

As already mentioned, the only attribute which is not optional is the NAME=VALUE pair. If you'd like your
cookie to remain available even after the user closes the browser, you should explicitly set an expiry date; if
not, the cookie will be destroyed once the browser is closed.

The Cookie object also comes with a couple of other interesting methods.

setValue(someString) − sets the value of the cookie to someString

getValue() − returns the current value of the cookie

setPath(someURL) − sets the PATH attribute of a cookie to someURL

getPath() − returns the current value of the PATH attribute

setMaxAge(someSeconds) − sets the EXPIRES attribute of the cookie, in seconds

getMaxAge() − returns the current value of the EXPIRES attribute

Learning To Write... 6
The JSP Files (part 6): State Of Grace

setDomain(someURL) − sets the DOMAIN attribute of the cookie

getDomain() − returns the current value of the DOMAIN attribute

setSecure(flag) − sets the SECURE attribute of the cookie as either true or false

getSecure() − returns the current value of the SECURE attribute

Note that you can only save string values in a cookie with setValue() − which entails a lot of
string−to−number−to−string conversions if you actually want to store a number (as in this example).

Learning To Write... 7
...And Read
So that takes care of writing a cookie − but how about reading it? Here's the code.

<%
// declare some variables
Cookie cookieCounter = null;

// the cookie you want


String cookieName = "counter";
int cookieFound = 0;

// a few more useful variables


String tempString;
int count=0;

// get an array of all cookies available on client


Cookie[] cookies = request.getCookies();

// iterate through array looking for your cookie


for(int i=0; i<cookies.length; i++)
{
cookieCounter = cookies[i];
if (cookieName.equals(cookieCounter.getName()))
{
cookieFound = 1;
break;
}

}
%>

Before you can read the cookie, you need to find it on the client's hard drive. Since JSP does not currently
allow you to directly locate and identify the cookie by name, you need to iterate through all available cookies
until you find the one you're looking for. In the example above, the "for" loop does just that; if and when it
finds the cookie, it sets the "cookieFound" variable to 1 and breaks out of the loop.

At this point, the cookie is stored in the Cookie object "cookieCounter". You can then use the getValue()
object method to get the current value of the cookie variable, and use it in your script.

...And Read 8
The JSP Files (part 6): State Of Grace
<%
// if found
if(cookieFound == 1)
{

// get the counter value as string


tempString = cookieCounter.getValue();

// convert it to a number
count = Integer.parseInt(tempString);

// increment it
count++;

// back to a string
tempString = Integer.toString(count);

// store it in the cookie for future use


cookieCounter.setValue(tempString);

// set some other attributes


cookieCounter.setMaxAge(300);
cookieCounter.setPath("/");

// send cookie to client


response.addCookie(cookieCounter);
}
%>

...And Read 9
What's In A Name?
Once you've understood these two fundamental techniques, the rest of the code should be simple to decipher.
If a cookie is found, the counter variable is incremented, and the setValue() method is used to write a new
value to the cookie; this counter variable is then displayed on the page. If a cookie is not found, it implies that
this is the user's first visit to the page (or a visit made after a previous cookie has expired); a new cookie is set
and an appropriate message displayed.

Again, since this example deals with numbers rather than strings, innumerable contortions are required to
convert the string value in the cookie to a number, increment it, and then convert it back to a string for storage
in the cookie.

Here's another example, this one a simple form. Enter your name and submit the form − a cookie will be
created containing the name you entered. When you next visit the page, your name will be automatically filled
in for you.

<%
// form.jsp

// declare some variables


Cookie thisCookie = null;

// the cookie you want


String cookieName = "username";
int cookieFound = 0;
String username = "";

// get an array of all cookies available on client


Cookie[] cookies = request.getCookies();

// iterate through array looking for your cookie


for(int i=0; i<cookies.length; i++)
{
thisCookie = cookies[i];
if (cookieName.equals(thisCookie.getName()))
{
cookieFound = 1;
break;
}

// if found
if(cookieFound == 1)
{

What's In A Name? 10
The JSP Files (part 6): State Of Grace
// get the counter value
username = thisCookie.getValue();
}
%>

<html>
<head>
<basefont face="Arial">
</head>

<body>

<form action="login.jsp" method="post">


<table>

<tr>
<td>Your name</td>
<td><input type=text name=username value="<%= username
%>"> <input
type="Submit" value="Click me"></td>
</tr>

</table>
</form>

</body>
</html>

This is the initial login form, "form.jsp" − as you can see, it checks for the presence of a cookie, and uses it to
fill in the account username if available.

When the form is submitted, "login.jsp" is called to process the data entered into the form; it will also set
cookie attributes appropriately.

<%
// login.jsp

// get values from form


String username = request.getParameter("username");

// create a new cookie to store the username


Cookie alpha = null;

What's In A Name? 11
The JSP Files (part 6): State Of Grace
alpha = new Cookie("username", username);
alpha.setMaxAge(300);
alpha.setPath("/");

// send it to client
response.addCookie(alpha);
%>

<html>
<head>
<basefont face="Arial">
</head>

<body>

Get lost, <b><%= username %></b>!

</body>
</html>

Simple, huh?

What's In A Name? 12
Plan B
The cookie−based approach is quite common; many Web sites use it, because it is flexible, simple, and
independent of the server−side language (once the cookie has been saved to the client's hard drive, you can
read it using JavaScript, or PHP, or JSP, or ...) The only problem: it is dependent on the cookie being accepted
by the client.

And so, another common approach is the use of a "session" to store specific bits of information when a client
visits a Web site; this session data is preserved for the duration of the visit, and is usually destroyed on its
conclusion. A session can thus be considered a basket of information which contains a host of variable−value
pairs; these variable−value pairs exist for the duration of the visit, and can be accessed at any point during it.
This approach provides an elegant solution to the "stateless" nature of the protocol, and is used on many of
today's largest sites to track and maintain information for personal and commercial transactions.

Every session created is associated with a unique identification string, or "session ID"; this string is sent to the
client, while a temporary entry with the same unique identification number is created on the server, either in a
flat file or in a database. It now becomes possible to register any number of "session variables" − these are
ordinary variables, which can be used to store textual or numeric information, and can be read from, or written
to, throughout the session.

The session ID is transmitted to the client either via a cookie, or via the URL GET method. The client, in turn,
must reference each request with this session ID, so that the server knows which session each client is
associated with and uses the appropriate session variables for each client. In case the client doesn't support
cookies and the URL method is rejected or not used, session management capabilities and session variables
will not be available to the client, and every request will be treated as though it were coming for the first time.

Sessions are typically left active for as long as the user's browser is open, or for a pre−defined period. Once
the user's browser is closed, or the specified time period is exceeded, the session and all variables within it are
automatically destroyed.

Plan B 13
Session Dissection
Creating a JSP session is much simpler than writing a cookie. To demonstrate this, here's the session
equivalent of the cookie−based counter you saw a few pages back.

<html>
<head>
</head>

<body>

<%
// get the value of the session variable
Integer visits = (Integer)session.getValue("counter");

// if null
if (visits == null)
{
// set it to 0 and print a welcome message
visits = new Integer(0);
session.putValue("counter", visits);
out.println("Welcome, stranger!");
}
else
{
// else increment and write the new value
visits = new Integer(visits.intValue() + 1);
session.putValue("counter", visits);
out.println("You have visited this page " + visits + "
time(s)! Don't you
have anything else to do, you bum?! ");
}
%>

</body>
</html>

There isn't much you have to do to create a session − simply use the putValue() method of the Session object
to create one or more session variable, and JSP will automatically create a session and register the variables.
You can then use the getValue() method to retrieve the values of the session variables automatically.

An important point to be noted here is that it is necessary to typecast the session variable while using
getValue() − in the example above, we've specifically stated the type of the variable in parentheses before

Session Dissection 14
The JSP Files (part 6): State Of Grace
assigning it to a regular JSP variable. Since JSP allows you to bind objects to the session, you can bind an
Integer object and thereby bypass some of the string−to−number conversion routines in the equvalent cookie
example.

With this information in mind, the example above becomes much simpler to read. An "if" statement is used to
take care of the two possible alternatives: a first−time visitor (no prior session) or a returning visitor
(pre−existing session). Depending on whether or not the "counter" variable exists, appropriate action is taken.

The Session object also comes with a bunch of other interesting methods − here are some of them:

getId() − returns a string containing the unique session ID

setMaxInactiveInterval(someSeconds) − keeps the session active for someSeconds duration after the last
client request

invalidate() − destroy the session

getAttribute() and setAttribute() − try these is getValue() and putValue() don't work

getCreationTime() − returns the time at which this session was created, in seconds, as an offset from midnight
January 1 1970

Session Dissection 15
Access Denied
Here's another simple example which demonstrates some of the methods above, and also illustrates how JSP
sessions can be used to protect Web pages with sensitive information.

This example presents a form ("start.html") asking for your name, and takes you to a new page ("login.jsp")
once you submit the form. "login.jsp" creates a session to store the name you entered, and offers a link to
"rootshell.jsp", which is the sensitive file to be protected.

So long as the session is active, any attempt to access the page "rootshell.jsp" will succeed. On the flip side, if
a session is not active, any attempt to access "rootshell.jsp" by bypassing the initial form will fail, and the user
will be redirected to "start.html".

This is a relatively primitive example, but serves to demonstrate one of the more common uses of session
variables.

All the redirection in this example is accomplished using the Response object (you remember this, don't you?)

<html>
<head>
<basefont face="Arial">
</head>

<body>
<!−− start.html −−>
<form action="login.jsp" method="post">
<table>

<tr>
<td>Your name</td>
<td><input type=text name=username> <input type="Submit"
value="Click
me"></td>
</tr>

</table>
</form>

</body>
</html>

Once the form is submitted, "login.jsp" takes over.

Access Denied 16
The JSP Files (part 6): State Of Grace

<html>
<head>
<basefont face="Arial"
</head>

<body>
<%

// get the form variable


String username = request.getParameter("username");

// create a session
session.putValue("username", username);

// set a timeout period


session.setMaxInactiveInterval(300);

// display a link to the protected file


out.println("Thank you for using this service.");
out.println("Click <a href=rootshell.jsp>here</a> for root
access");
%>

</body>
</html>

And here's the top−secret page.

<html>
<head>
<basefont face="Arial">
</head>

<body>
<%
// rootshell.jsp

// get the username from the session


String username = (String)session.getValue("username");

Access Denied 17
The JSP Files (part 6): State Of Grace
// if null, security breach!
if (username == null)
{
response.setHeader("Location", "start.html");
}
else
{
// display the protected page
%>

Welcome to your root shell, <b><%= username %></b>!


<p>
Your session ID is <% out.println( session.getId() ); %>
<p>
This session will expire in <% out.println(
session.getMaxInactiveInterval() ); %> seconds.

<%
}
%>

</body>
</html>

To test this, first log in and find your way to "rootshell.jsp" − you should have no trouble accessing it. Then
close the browser, start it up again, and try to get to "rootshell.jsp" without going through the login process;
you should be automatically redirected to the login page.

And that's about it. You should now have a pretty clear idea of how JSP attempts to solve the "stateless
protocol" problem, together with some understanding of how to create and use both client−side cookies and
server−side sessions. Go practice!

Access Denied 18

You might also like