Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Protect Web application control flow

Protect Web application control flow

Tutorial Details:

Java Tip 136: Protect Web application control flow
Java Tip 136: Protect Web application control flow
By: By Romain Guay
A strategy built on Struts manages duplicate form submission
eb application designers and programmers often face situations where a form submission must be protected against a rupture in the normal control flow sequence. This situation typically occurs when a user clicks more than once on a submit button before the response is sent back or when a client accesses a view by returning to a previously bookmarked page. Control flow sequence is particularly important to preserve when form submission involves transaction processing on the server.
This article proposes a well-encapsulated solution to this problem: a strategy implemented as an abstract class that leverages the Struts framework.
Note: You can download this article's source code from Resources .
Client vs. server solutions
Different solutions can solve this multiple form submission situation. Some transactional sites simply warn the user to wait for a response after submitting and not to submit twice. More sophisticated solutions involve either client scripting or server programming.
In the client-only strategy, a flag is set on the first submission, and, from then on, the submit button is disabled based on this flag. While appropriate in some situations, this strategy is more or less browser dependent and not as dependable as server solutions.
For a server-based solution, the Synchronizer Token pattern (from Core J2EE Patterns ) can be applied, which requires minimal contribution from the client side. The basic idea is to set a token in a session variable before returning a transactional page to the client. This page carries the token inside a hidden field. Upon submission, request processing first tests for the presence of a valid token in the request parameter by comparing it with the one registered in the session. If the token is valid, processing can continue normally, otherwise an alternate course of action is taken. After testing, the token resets to null to prevent subsequent submissions until a new token is saved in the session, which must be done at the appropriate time based on the desired application flow of control. In other words, the one-time privilege to submit data is given to one specific instance of a view. This Synchronizer Token pattern is used in the Apache Jakarta Project's Struts framework, the popular open source Model-View-Controller implementation.
A synchronized action
Based on the above, the solution appears complete. But an element is missing: how do we specify/implement the alternate course of action when an invalid token is detected. In fact, given the case where the submit button is reclicked, the second request will cause the loss of the first response containing the expected result. The thread that executes the first request still runs, but has no means of providing its response to the browser. Hence, the user may be left with the impression that the transaction did not complete, while in reality, it may have successfully completed.
This tip's proposed strategy builds on the Struts framework to provide a complete solution that prevents duplicate submission and still ensures the display of a response that represents the original request's outcome. The proposed implementation involves the abstract class SynchroAction , which actions can extend to behave in the specified synchronized manner. This class overrides the Action.perform() method and provides an abstract performSynchro() method with the same arguments. The original perform method dispatches control according to the synchronization status, as shown in the listing below:
public final ActionForward perform(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
HttpSession session = request.getSession();
ActionForward forward = null;
if (isTokenValid(request)) {
// Reset token and session attributes
reset(request);
try {
// Perform the action and store the results
forward = performSynchro(mapping, form, request, response);
session.setAttribute(FORM_KEY, form);
session.setAttribute(FORWARD_KEY, forward);
ActionErrors errors = (ActionErrors)
request.getAttribute(Action.ERROR_KEY);
if (errors != null && !errors.empty()) {
saveToken(request);
}
session.setAttribute(ERRORS_KEY, errors);
session.setAttribute(COMPLETE_KEY, "true");
} catch (IOException e) {
// Store and rethrow the exception
session.setAttribute(EXCEPTION_KEY, e);
session.setAttribute(COMPLETE_KEY, "true");
throw e;
} catch (ServletException e) {
// Store and rethrow the exception
session.setAttribute(EXCEPTION_KEY, e);
session.setAttribute(COMPLETE_KEY, "true");
throw e;
}
} else {
// If the action is complete
if ("true".equals(session.getAttribute(COMPLETE_KEY))) {
// Obtain the exception from the session
Exception e = (Exception) session.getAttribute(EXCEPTION_KEY);
// If it is not null, throw it
if (e != null) {
if (e instanceof IOException) {
throw (IOException) e;
} else if (e instanceof ServletException) {
throw (ServletException) e;
}
}
// Obtain the form from the session
ActionForm f = (ActionForm) session.getAttribute(FORM_KEY);
// Set it in the appropriate context
if ("request".equals(mapping.getScope())) {
request.setAttribute(mapping.getAttribute(), f);
} else {
session.setAttribute(mapping.getAttribute(), f);
}
// Obtain and save the errors from the session
saveErrors(request, (ActionErrors)
session.getAttribute(ERRORS_KEY));
// Obtain the forward from the session
forward = (ActionForward) session.getAttribute(FORWARD_KEY);
} else {
// Perform the appropriate action in case of token error
forward = performInvalidToken(mapping, form, request, response);
}
}
return forward;
}
As you see above, the protected action is performed only once, that is, if the token is valid. If other requests are received while the action is running, they are directed to the performInvalidToken() method's result until the action completes. By default, this method simply returns an ActionForward named "synchroError" . This forward should lead to a page signaling that the action is in progress and providing a button to continue. This button simply resubmits to the same action without any form or parameter in the request (they will not be considered anyway). When the action completes, it stores its forward, form, exception, and errors, if any, in the session, and it sets a flag to indicate it has completed. The first request coming after the action completion will get the forward, form, exception, and errors from the session and continue as if it was the first request itself.
I include an example in the source code to demonstrate the behavior of a simple synchronized action. The provided implementation is based on Struts 1.0.2, but can easily be adapted for release 1.1.
Preserve consistent flow control
Multiple form submissions may cause inconsistency in transactions and must be avoided. For that purpose, the Synchronizer Token pattern is a great help. This article's proposed strategy nicely complements this pattern in recovering the response to the original request and, as such, helps preserve a consistent flow of control in Web applications.
This page formated for crawlers and browsers that don't support scripts and tables.
Home
EZone


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Protect Web application control flow

View Tutorial:
Protect Web application control flow

Related Tutorials:

Java gets serial support with the new javax.comm package - JavaWorld - May 1998
Java gets serial support with the new javax.comm package - JavaWorld - May 1998
 
Java gets serial support with the new javax.comm package
Java gets serial support with the new javax.comm package
 
A promise of easier embedded-systems networking - JavaWorld November 1999
A promise of easier embedded-systems networking - JavaWorld November 1999
 
Secure a Web application, Java-style - JavaWorld April 2000
Secure a Web application, Java-style - JavaWorld April 2000
 
Take control of the servlet environment, Part 1 - JavaWorld November 2000
Take control of the servlet environment, Part 1 - JavaWorld November 2000
 
Use Web services to integrate Web applications with EISs
Use Web services to integrate Web applications with EISs
 
Mix protocols transparently in Web applications
Mix protocols transparently in Web applications
 
Java scripting languages: Which is right for you?
Java scripting languages: Which is right for you?
 
How to build an interpreter in Java, Part 1: The BASICs (JavaWorld / May 1997 / by Chuck McManis)
How to build an interpreter in Java, Part 1: The BASICs (JavaWorld / May 1997 / by Chuck McManis)
 
All that JAAS
All that JAAS
 
A first look at JavaServer Faces, Part I
A first look at JavaServer Faces, Part Learn how to implement Web-based user interfaces with JSF
 
Protect Web application control flow
Protect Web application control flow
 
Jump the hurdles of Struts development
Jump the hurdles of Struts development
 
Datastructures and algorithms, Part 1
Datastructures and algorithms, Part 1
 
Cracking Java byte-code encryption
Cracking Java byte-code encryption
 
Java and Security, Part 1
Java and Security WebLogic provides a comprehensive suite of security services that can be used to protect all aspects of a domain and its deployments. These security services affect all aspects of your domain: from the lowest level provided by the Jav
 
Smokescreen Introduction
Smokescreen is a Java obfuscator. Aside from being able to change symbolic names, it can also modify the bytecode instructions in methods thereby obfuscating control flow. This makes the resulting obfuscated classes much more difficult to decompile.
 
Smokescreen 3.4 has been released
Smokescreen is a Java obfuscator. Aside from being able to change symbolic names, it can also modify the bytecode instructions in methods thereby obfuscating control flow. This makes the resulting obfuscated classes much more difficult to decompile.
 
Networking our whiteboard with servlets.
Find out how to easily replace the RMI and sockets networking layers with servlets.
 
Integrating Java Open Single Sign-On in Pluto
This article shows how to integrate Java Open Single Sign-On in Apache\'s Pluto portlet container.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.