Skip to main content

Storing Secure Session State on The Client

Posted by gmurray71 on May 17, 2005 at 5:03 PM PDT

A few years back I developed a custom tag library for The Java Pet Store to get around back button
issues when a user decided to change the locale of the Java Pet Store. This was made possible by
storing all the objects related to a specific request inside each HTML page using a application
specific custom tag library. This technique was later adopted by Java ServerFaces to store the
component tree information on the client.

In the BluePrints Solutions Catalog we
generalized this technique of using a JSP custom tag library to allow a developer to easily and
securely store state on the client. The following JSP fragment shows how simple it can be to securely store
session state on the client.

<cs:client-state action="word" beanName="sampleBean" secure="true">
<table>
  <c:forEach var="word" varStatus="status" begin="0" items="${sampleBean.words}">
   <tr>
    <td>
     <input type="checkbox" name="word_${status.index}" value="${word}">
      ${word}
     </input>
    </td>
   </tr>
  </c:forEach>
  <tr>
   <td>
    New Word: <input type="text" name="newWord" size="25"/>
   </td>
  </tr>
  <tr>
   <td>
    <input type="submit" value="Update List"/>
   </td>
  </tr>
</table>
</cs:client-state>

The client-state tag acts like a form tag and wrapping a form submission. In the case the attribute
"beanName" specifies a Java object (which implements java.io.Serializable) that is
stored on the client. The "sampleBean" must exist in the HttpServletRequest
scope with id "sampleBean". The "sampleBean" Java object is serialized and encrypted
when the request is dispatched to the JSP page and the client-state tag is encountered.
The resulting HTML page will look as follows.

<form method="POST" action="word">
  <input type="hidden" name="beanName" value="sampleBean" />
  <input type="hidden" name="sampleBean" value="rO0ABXNy
AC5jb20uc3VuLmoyZWUuYmx1ZXByaW50cy5jbGllbnRzdGF0ZS5TYW1w
bGVCZWFuhCyFzCR588MCAAJMAAhuZXh0UGFnZXQAEkxqYXZhL2xhbmcv
U3RyaW5nO0wABXdvcmRzdAAVTGphdmEvdXRpbC9BcnJheUxpc3Q7eHBw
c3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4
cAAAAAJ3BAAAAAp0AARncmVndAAFaW5kZXJ4" />
<table>
   <tr>
    <td>
     <input type="checkbox" name="word_0" value="greg">
      greg
     </input>
    </td>
   </tr>
   <tr>
    <td>
     <input type="checkbox" name="word_1" value="inder">
      inder
     </input>
    </td>
   </tr>
  <tr>
   <td>
    New Word: <input type="text" name="newWord" size="25"/>
   </td>
  </tr>
  <tr>
   <td>
    <input type="submit" value="Update List"/>
   </td>
  </tr>
</table>
</form>

Notice that the form above contains a hidden field with the name "sampleBean" and value containing
encrypted base64 encoded data. This is the serialized "sampleBean" object from the
HttpServletRequest scope.

Before handling a request from a page containing the client-state tag the state must be decoded from base64
and decrypted (if secure is set to "true").

A utility class is provided as part of the client-state tag library to facilitate the decoding and decrypting
as may be seen in the code sample below.

ClientStateDeserializer.deserialize(request,response);

This code above reconsitute the "sampleBean" Java object and place it in the
HttpServletRequest scope.

After processing the request the server-side component may dispatch to a page that contains the
same Java object. The end result is that the "sampleBean" object never exists outside
of the HttpServletRequest scope.

Storing state on the client has the following benefits:

  • Scalability - A single server can support more clients. An increase in clients does not require more memory or database resources on the server.
  • Back Button is not a Problem - All state is saved in the page making the back button no longer an issue. What you see in the HTML page is the Java object used to generate that page.
  • Session Time-Outs not an Issue - HttpSession time outs are not a problem.

Saving state on the client does not come for free. Here are some of the drawbacks:

  • Computing Resources - There is a CPU cost associated with encoding/decoding and encrypting/decrypting of state for each interaction.
  • Bandwidth - Since all the state related to a page is sent back to the server on each request there will be more data sent.
  • Navigation must be from a form - The state is kept as HTML form hidden variables requiring
    page to page navigation to be from a form though links could use JavaScript to performs a form submits.
  • Browser Crashes - If the browser that contains the state crashes the state is lost.

What do you think about storing state on the client?

For a much more detailed description of the idea of client-side state management see:

https://bpcatalog.dev.java.net/nonav/webtier/clientside-state/frames.html

To download the client-state tag from:

https://blueprints.dev.java.net/files/documents/1713/14760/clientstate-installer.jar