Chapter 6 Session Management

Download Report

Transcript Chapter 6 Session Management

Chapter 6 Session Management
Web servers have no short-term
memory
• As soon as web servers send you a response, they
forget who you are, the next time you make a
request, they don’t recognize you
– They do not remember what you’ve requested in the
past, and they don’t remember what they’ve sent you
in response
• Sometimes you need to keep conversational state
with the client across multiple requests
– A shopping cart wouldn’t work if the client had to
make all his choices and then checkout in a single
request
Kim wants to keep client-specific
state across multiple requests
How can he track the client’s answers
• Kim’s design won’t work unless he can keep
track of everything the client has already said
during the conversation, not just the answer
in the current question.
– The advice engine he plan to write uses all of that
client’s previous answers to come up with either
another question to ask, or a final
recommendation
HttpSession
• Kim can use an HttpSession object to hold the
conversational state across multiple requests.
– In other words, for an entire session with that
client
How does the Container know who the
client is?
• The HTTP protocol uses stateless connections.
– The client browser makes a connection to the server, sends
the request, gets the response, and closes the connection
– In other words, the connection exists for only a single
request/response.
• Because the connections don’t persist, the container
doesn’t recognize that the client making a second
request is the same client from a previous request.
– As far as the container’s concerned, each request is from a
new client.
Question
• Why can’t the container just use the IP
address of the client?
• Answer: If the client is on a LAN (local area
network), the IP is only unique inside the LAN.
Also, your IP address may not be the one that
outside world sees.
The client needs a unique session ID
• The idea is simple: on the client’s first request,
the container generates a unique session ID
and gives it back to the client with the
response
– The client sends back the session ID with each
subsequent request
• The container sees the ID, finds the matching session,
and associates the session with the request
How do the client and Container
exchange Session ID info?
• Somehow, the container has to get the session
ID to the client as part of the response, and
the client has to send back the session ID as
part of the request.
– One way to do it is through cookies
How do the client and Container
exchange Session ID info?
How do the client and Container
exchange Session ID info?
The container does virtually all the
cookie work
• You do have to tell the container that you
want to create or use a session, but the
container takes care of generating the session
ID, creating a new Cookie object, stuffing the
session ID into the cookie, and setting the
cookie as part of the response
The container does virtually all the
cookie work
What if I want to know whether the session
already existed or was just created?
• The no-arg request method, getSession(),
returns a session regardless of whether there
is a pre-existing session.
– Since you always get an HttpSession instance
back from that method, the only way to know if
the session is new is to ask the session.
URL rewriting
• Some client may configure browser to refuse cookies
• You can do sessions even if the client doesn’t accept
cookies, but you have to do a little more work…
– A little more work means you have the encode your URLs
• If the client won’t take cookies, you can use URL
rewriting as a backup
• URL rewriting takes the session ID that is in the
cookie and sticks it right onto the end of every URL
that comes in to this app
URL rewriting
URL rewriting
URL rewriting
• If cookies don’t work, the container falls back to URL
rewriting, but only if you’ve done the extra work of encoding
all the URLs you send in the response.
Example line of code in a servlet:
– out.println(“<a href=\”” + response.encodeURL(“\ski”) + “\”>Click
me</a> “);
• If you don’t explicitly encode you URLs, and the client won’t
accept cookies, you don’t get to use session management
mechanisms provided by the container.
– If you do encode your URLs, the container will first attempt to use
cookies for session management, and fall back to URL rewriting only if
the cookie approach fails
URL rewriting
• URL rewriting is handled in a vendor-specific
way.
– Tomcat uses a semicolon “;” to append the extra
info to the URL. Another vendor might use a
comma or something else.
Setting session timeout
• Three ways a session can die
– It times out
– You call invalidate() on the session object
– The application goes down (crashes or is
undeployed)
Setting session timeout
Setting session timeout
General Session Management
Mechanism
• Our book only talk about using cookie and URL rewriting
(implemented by the container) to do session management
• Generally speaking, there are 3 ways to do session
management
– URL rewriting
• Implemented by the container (vendor specific implementation)
– URLs have to be encoded and the application is not robust, application may
fail if the application run on another vendor’s application server
• Implemented by the developer (always work regardless of the vendor)
– Hidden form field
– cookie
Example 1: Session Management using
URL rewriting (implemented by the developer)
Note: The URL rewriting we demonstrated here
is not vendor specific and you do not have to
encode the URL
Page 1:
Page 2:
index.html
Servlet
Toppings.java
Page 3:
Servlet
PizzaOrder.java
The problem is: How can page 3 know what is the crust
selected at page 1?
Page 2 has to somehow send the crust info to page 3. One method is to append that info as a
request parameter in the URL. Since the parameter will change based on the user’s choie in
page 1, we call this technique URL rewriting.
•The part highlighted red will change when a different crust is selected
Page 2:
Page 3:
Page 1:
Servlet
Servlet
index.html
Toppings.java
PizzaOrder.java
<html>
String crustType =
request.getParameter("crust");
<body>
<form method="POST“
action="Toppings">
Please select your pizza crust:<br />
<input type="radio" name="crust"
value="Hand Tossed" />Hand
Tossed<br />
<input type="radio" name="crust"
value="Thin Crust" />Thin Crust<br />
<input type="radio" name="crust"
value="Deep Dish" />Deep Dish<br />
<input name="Next" type="submit"
value="Next" /><br />
</form>
</body>
</html>
out.println(
"<html>"+
"<body link=\"#000080\">"+
""+
"<form method=\"POST\"
action=\"PizzaOrder?crust="+crustType+"\">"+
"Please select your toppings:<br />" +
"<input type=\"checkbox\" name=\"topping\"
value=\"Sausage\" />Sausage<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepperoni\" />Pepperoni<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Tomato\" />Tomato<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Mushroom\" />Mushroom<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepper\" />Pepper<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Chicken\" />Chicken<br />"+
…………………..
String strCrust =
request.getParameter("crust");
String[] strToppings =
request.getParameterValues("topping");
out.println(
"<html>"+
""+
"<body link=\"#000080\"
bgcolor=\"#009999\">"+
""+
"<p>Your choice of pizza is: <br />" +
"Crust: " + strCrust + "<br />" +
"Toppings: ");
for(int index=0; index < strToppings.length;
index++)
{
out.println(strToppings[index] + " ");
}
…………..
Example 2: Session Management using
Hidden Form Field
Hidden Form Field
• Hidden form fields are similar to text fields, but does
not show on the page.
• The visitor can't type anything into a hidden field,
which leads to the purpose of the field.
• How to use:
<input type="hidden" name="<Name of the
field>" value="<Default value of the object>">
Another way for page 2 to send the crust info to page 3 is to use hidden form field. The value of the hidden
form field will change based on the user’s choie in page 1.
•The part highlighted red will change when a different crust is selected
Page 1:
index.html
<html>
<body>
<form method="POST“ action="Toppings">
Please select your pizza crust:<br />
<input type="radio" name="crust" value="Hand
Tossed" />Hand Tossed<br />
<input type="radio" name="crust" value="Thin
Crust" />Thin Crust<br />
<input type="radio" name="crust" value="Deep
Dish" />Deep Dish<br />
<input name="Next" type="submit" value="Next"
/><br />
</form>
</body>
</html>
Page 2:
Page 3:
Servlet
Servlet
Toppings.java
PizzaOrder.java
String crustType =
request.getParameter("crust");
out.println(
"<html>"+
""+
"<body link=\"#000080\">"+
""+
"<form method=\"POST\"
action=\"PizzaOrder\">"+
"Please select your toppings:<br />" +
"<input type=\"checkbox\" name=\"topping\"
value=\"Sausage\" />Sausage<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepperoni\" />Pepperoni<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Tomato\" />Tomato<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Mushroom\" />Mushroom<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepper\" />Pepper<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Chicken\" />Chicken<br />"+
"<input type=\"hidden\" name=\"crust\" value=\""
+ crustType + "\">"+
" <br />" +
……………
String strCrust =
request.getParameter("crust");
String[] strToppings =
request.getParameterValues("topping");
out.println(
"<html>"+
""+
"<body link=\"#000080\"
bgcolor=\"#009999\">"+
""+
"<p>Your choice of pizza is: <br />" +
"Crust: " + strCrust + "<br />" +
"Toppings: ");
for(int index=0; index < strToppings.length;
index++)
{
out.println(strToppings[index] + " ");
}
…………..
Example 3: Session Management using
cookie
Another way for page 2 to send the crust info to page 3 is to use cookie (through HttpSession
object)
Page 1:
index.html
<html>
Page 2:
Page 3:
Servlet
Servlet
Toppings.java
PizzaOrder.java
String crustType = request.getParameter("crust");
<body>
<form method="POST“ action="Toppings">
Please select your pizza crust:<br />
<input type="radio" name="crust" value="Hand
Tossed" />Hand Tossed<br />
<input type="radio" name="crust" value="Thin
Crust" />Thin Crust<br />
<input type="radio" name="crust" value="Deep
Dish" />Deep Dish<br />
<input name="Next" type="submit" value="Next"
/><br />
</form>
</body>
</html>
HttpSession session = request.getSession();
session.setAttribute("crust", crustType);
out.println(
"<html>"+
""+
"<head>"+
"<title>Toppings</title>"+
"</head>"+
""+
"<body link=\"#000080\">"+
""+
"<form method=\"POST\" action=\"PizzaOrder\">"+
"Please select your toppings:<br />" +
"<input type=\"checkbox\" name=\"topping\"
value=\"Sausage\" />Sausage<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepperoni\" />Pepperoni<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Tomato\" />Tomato<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Mushroom\" />Mushroom<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepper\" />Pepper<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Chicken\" />Chicken<br />"+
…………………
HttpSession session = request.getSession();
String strCrust = (String) session.getAttribute("crust");
String[] strToppings =
request.getParameterValues("topping");
out.println(
"<html>"+
""+
"<head>"+
"<title>New Page 1</title>"+
"</head>"+
""+
"<body link=\"#000080\" bgcolor=\"#009999\">"+
""+
"<p>Your choice of pizza is: <br />" +
"Crust: " + strCrust + "<br />" +
"Toppings: ");
for(int index=0; index < strToppings.length; index++)
{
out.println(strToppings[index] + " ");
}
Value of the cookie at each page
Note: The values of the cookie on page 2 and 3 are the same
Page 1:
Page 2:
Page 3:
index.html
Servlet
Servlet
Toppings.java
PizzaOrder.java
Note: The cookie info here is displayed using a free add-on to
firefox called “Web Developer”
Example 4: Session Management using
URL rewriting (implemented by the container)
Page 2 Servlet :
Toppings.java
String crustType =
request.getParameter("crust");
HttpSession session = request.getSession();
session.setAttribute("crust", crustType);
Page 1:
index.html
<html>
<body>
<form method="POST“
action="Toppings">
Please select your pizza crust:<br />
<input type="radio" name="crust"
value="Hand Tossed" />Hand Tossed<br
/>
<input type="radio" name="crust"
value="Thin Crust" />Thin Crust<br />
<input type="radio" name="crust"
value="Deep Dish" />Deep Dish<br />
<input name="Next" type="submit"
value="Next" /><br />
</form>
</body>
</html>
out.println(
"<html>"+
""+
"<body link=\"#000080\">"+
""+
"<form method=\"POST\" action=\"" +
response.encodeURL("PizzaOrder") + "\">"+
"Please select your toppings:<br />" +
"<input type=\"checkbox\" name=\"topping\"
value=\"Sausage\" />Sausage<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Pepperoni\" />Pepperoni<br />"+
"<input type=\"checkbox\" name=\"topping\"
value=\"Tomato\" />Tomato<br />"+
<html>
<body link="#000080">
<form method="POST"
action="PizzaOrder;jsessionid=0E3042CCC1
98EF1497EED823D58799B3">
Please select your
toppings:<br />
<input type="checkbox"
name="topping" value="Sausage"
/>Sausage<br />
<input type="checkbox"
name="topping" value="Pepperoni"
/>Pepperoni<br />
<input type="checkbox"
name="topping" value="Tomato"
/>Tomato<br />
<input type="checkbox"
name="topping" value="Mushroom"
/>Mushroom<br />
………………..
Page 3:
Servlet
PizzaOrder.java
HttpSession session = request.getSession();
String strCrust = (String) session.getAttribute("crust");
String[] strToppings =
request.getParameterValues("topping");
out.println(
"<html>"+
""+
"<head>"+
"<title>New Page 1</title>"+
"</head>"+
""+
"<body link=\"#000080\" bgcolor=\"#009999\">"+
""+
"<p>Your choice of pizza is: <br />" +
"Crust: " + strCrust + "<br />" +
"Toppings: ");
for(int index=0; index < strToppings.length; index++)
{
out.println(strToppings[index] + " ");
}