Thursday 7 November 2013

Duplicate Form Submission Prevent and Solutions

Here Duplicate form submission  applied in login page only. If we want we can extend to some other modules also.
For this we need one Login.jsp, struts.xml,LoginAction.action,invalidToken.jsp,and struts2-Core jar. 

Step 1: Login.jsp
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Duplicate Request Page</title> </head> <body>

<s:form action="loginAct" id="loginForm" method="post" >
   <input type="text" name="strUserID" id="strUserID" value="User ID"/><br/><br/>
   <input type="password" name="strPassword" id="strPassword" value="Password"  /><br/>
   <s:token/>
</s:form>

</body>
</html>

Step 2: Add below interceptors in your struts.xml file

<interceptors>
      <interceptor-stack name="defaultSecurityStack">
        <interceptor-ref name="token">
          <param name="excludeMethods">*</param>
          <param name="includeMethods">loginExecute</param>
        </interceptor-ref>
        <interceptor-ref name="SessionCheckInterceptor"/>
        <interceptor-ref name="ClearCachingInterceptor"/>
        <interceptor-ref name="defaultStack"/>
      </interceptor-stack>

      <interceptor name="SessionCheckInterceptor" class="com.test.SessionCheckInterceptor" />
      <interceptor name="ClearCachingInterceptor" class="com.test.CachingHeadersInterceptor" />
</interceptors>

    <default-interceptor-ref name="defaultSecurityStack" />

<global-results>
      <result name="error">/error</result>
      <result name="sessionexpired" >sessionExpired.jsp</result>
      <result name="invalid.token">invalidToken.jsp</result>
</global-results>

Here, SessionCheckInterceptor and ClearCachingInterceptor are application oriented Interceptors(Own interceptors).
First, defaultSecurityStack will call and then it will create the token and then moved to action.
Here, exclude all the methods in your application using <param name="excludeMethods">*</param> tag.
but include only one method using <param name="includeMethods">loginExecute</param>.
If we want to include any other methods we can add in "includeMethods".
If we get any invalid token then it will check in Global result and execute the invalidToken.jsp page.

Step 3: Create invalidToken.jsp page 

<html> 
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> 
<title>Duplicate Request Page</title> 
</head> 
<body> 
<h3>Duplicate request detected.</h3>
 <ul>
 <li>Back button usage to submit form again</li>
 <li>Double click on Submit button</li> 
 <li>Using "Reload" Option in browser</li>
</ul> <br> 
<s:if test="hasActionErrors()"> <s:actionerror/> 
</s:if>
</body> 
</html>

Step 4: Need Action Page

public class LoginAction extends ActionSupport
public String loginExecute(){


String sForward="failure";

strUserID=strUserID.trim();
strPassword=strPassword.trim();

Map<String, Object> session = ActionContext.getContext().getSession();
try{
sForward = checkEmptyUserID(session, strUserID, strPassword);
userLoginDetails(sForward);
}catch(Exception exception){
exception = exception;
return ERROR;

}
return sForward;
}
Step 5: Need a Pojo class for username,password in Login page.


Explanation: 

First Login.jsp creates the token on submit of the form. And then Interceptor
will work. Lets see how token interceptors will work to handle multiple form 
submissions: 

  1. When a request is made to the update action, Struts2 tags API generates a unique token and set it to the session. The same token is sent in the HTML response as hidden field.
  2. When the form is submitted with token, it is intercepted by token interceptor where it tries to fetch the token from the session and validate that it’s same as the token received in the request form. If token is found in session and validated then the request is forwarded to the next interceptor in the chain. Token interceptor also removes the token from the session.
  3. When the same form is submitted again, token interceptor will not find it in the session. So it will add an action error message and return invalid.token result as response. You can see this message in above invalidToken.jsp. This way token interceptor make sure that a form with token is processed only once by the action.





No comments:

Post a Comment

SpringBoot

SpringBoot SpringBoot Application :  Pros & Cons :  SpringBoot Application creation using spring.io :  SpringBoot Application Annotation...