Javaweb Avoid duplicate submissions of forms __java

Source: Internet
Author: User
Tags md5 stringbuffer
duplicate submission of form

index.jsp

<form action= "<%=request.getcontextpath ()%>/tokenservlet" method= "POST" >
	name: <input type= " Text "name=" name "/> 
	<input type=" Submit "value=" Submit "/>
</form>


Tokenservlet.java

Package COM.XYC;

Import java.io.IOException;
Import javax.servlet.ServletException;
Import Javax.servlet.annotation.WebServlet;
Import Javax.servlet.http.HttpServlet;
Import Javax.servlet.http.HttpServletRequest;

Import Javax.servlet.http.HttpServletResponse;

    public class Tokenservlet extends HttpServlet {private static final long serialversionuid = 1L; protected void DoPost (HttpServletRequest request, httpservletresponse response) throws Servletexception, Ioexc eption {try {thread.sleep (2000);//Analog Network latency} catch (Interruptedexception e) {E.PR
        Intstacktrace ();
        
        } request.setcharacterencoding ("UTF-8");

        String name = Request.getparameter ("name");

        System.out.println ("Name:" + name);
        Request.getrequestdispatcher (Request.getcontextpath () + "/token/success.jsp"). Forward (request, response); Response.sendredirect (Request.getcontextpath () + "/tokeN/success.jsp ");
 }

}

success.jsp

 

Duplicate Submission of form:

I. Duplication of submissions:

①. When the form is submitted to a servlet, and the servlet responds to a JSP page by requesting forwarding, the address bar retains the path of the servlet, clicking Refresh on the corresponding page

②. Due to the network reason in the corresponding page did not arrive is a repeat click submit the form

③. Click "Back" and click "Submit" again.

④. Redirection will also reproduce the situation described above ②③, but the address bar path will change after redirection, so there is no ①

Ii. The situation is not a duplicate submission

Click "Back", "Refresh" the original form page, and then "submit", does not belong to duplicate submissions


How to avoid duplicate submission of forms

Solution:

①. Provides only one hidden field: <input type= "hidden" name= "token" value= "Tokenvalue"/> unworkable: because there is no way to clear a fixed request parameter

②. Put the tag in the request, it doesn't work because the reason for the request scope, after the form was refreshed, the request has been destroyed before the submission form is a new request.

③. Put the markers in the session, you can

> In the form page, generate a random value token

> in the original form page, put the token value into the session

> in the original form, put the token value into the hidden field


> in the target servlet: Get the token value in the session and hidden fields

> Compare two values for consistency: if consistent, accept requests and purge token from the session domain. If inconsistent, respond directly to the prompt page "form repeat submission"


Achieve one:

index.jsp

<%
	String tokenvalue = new Date (). GetTime () + "";
	Session.setattribute ("token", tokenvalue);
%>

<form action= "<%=request.getcontextpath ()%>/tokenservlet" method= "POST" >

<input Type = "hidden" name= "token"  value= "<%=tokenvalue%>"/>
	name: <input type= "text" name= "name"/> 
	<input type= "Submit" value= "Submit"/>
</form>

Tokenservlet.java

Package COM.XYC;

Import java.io.IOException;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServlet;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;

Import javax.servlet.http.HttpSession;

    public class Tokenservlet extends HttpServlet {private static final long serialversionuid = 1L; protected void DoPost (HttpServletRequest request, httpservletresponse response) throws Servletexception, Ioexc
        eption {try {thread.sleep (2000);
        catch (Interruptedexception e) {e.printstacktrace ();

        } request.setcharacterencoding ("UTF-8");

        String name = Request.getparameter ("name");
        HttpSession session = Request.getsession ();
        Object token = Session.getattribute ("token");
        
        String Tokenvalue = Request.getparameter ("token");
        SYSTEM.OUT.PRINTLN (token);
        System.out.println (Tokenvalue); System.out.priNtln ("Name:" + name);
        if (token!= null && token.equals (tokenvalue)) {Session.removeattribute ("token");
            else {response.sendredirect (Request.getcontextpath () + "/token/token.jsp");
        Return
        }//request.getrequestdispatcher (Request.getcontextpath () + "/token/success.jsp"). Forward (Request,response);
    Response.sendredirect (Request.getcontextpath () + "/token/success.jsp");
 }

}

success.jsp

 

implement two (emulate the implementation of struts):

Tokenprocessor.java

The tool class used to manage the form identification number, which is used primarily to generate, compare, and purge form identification numbers stored in the current user session. To ensure the uniqueness of the form identification number, each time the combined value of the current SessionID and system time is calculated as the form identification number by the MD5 algorithm, and the Tokenprocessor class is designed as a single instance class

Package COM.XYC;
Import Javax.servlet.http.HttpServletRequest;

Import javax.servlet.http.HttpSession;
Import Java.security.MessageDigest;

Import java.security.NoSuchAlgorithmException;

	public class Tokenprocessor {private static final String Token_key = "Token_key";

	private static final String Transaction_token_key = "Transaction_token_key";

	private static Tokenprocessor instance = new Tokenprocessor ();

	Private long previous;
	Protected Tokenprocessor () {super ();
	public static Tokenprocessor getinstance () {return instance;
	Public synchronized Boolean istokenvalid (HttpServletRequest request) {return This.istokenvalid (request, false); Public synchronized Boolean istokenvalid (HttpServletRequest request, Boolean reset) {HttpSession session = Reque

		St.getsession (FALSE);
		if (session = = NULL) {return false;

		String saved = (string) session.getattribute (Transaction_token_key);
		if (saved = = null) {return false;
	} if (reset) {		This.resettoken (Request);

		String token = request.getparameter (Token_key);
		if (token = = null) {return false;
	return saved.equals (token);

		synchronized void Resettoken (HttpServletRequest request) {HttpSession session = Request.getsession (false);
		if (session = null) {return;
	} session.removeattribute (Transaction_token_key);
		Synchronized String Savetoken (HttpServletRequest request) {HttpSession session = Request.getsession ();

		String token = generatetoken (request);
		if (token!= null) {Session.setattribute (Transaction_token_key, token);
	return token;

		Synchronized String Generatetoken (HttpServletRequest request) {HttpSession session = Request.getsession ();
	Return Generatetoken (Session.getid ());

			Public synchronized string Generatetoken (string id) {try {long = System.currenttimemillis ();
			if (current = = previous) {current++;

			} previous = current; Byte[] Now = new Long (current). ToString (). GetBytes ();

			MessageDigest MD = messagedigest.getinstance ("MD5");
			Md.update (Id.getbytes ());

			Md.update (now);
		Return Tohex (Md.digest ());
		catch (NoSuchAlgorithmException e) {return null;

		} private String Tohex (byte[] buffer {stringbuffer SB = new StringBuffer (Buffer.length * 2);
			for (int i = 0; i < buffer.length i++) {sb.append (Character.fordigit ((buffer[i) & 0xf0) >> 4, 16));
		Sb.append (Character.fordigit (Buffer[i] & 0x0f, 16));
	return sb.tostring ();
 }
}

index.jsp

<%--<%
	String tokenvalue = new Date (). GetTime () + "";
	Session.setattribute ("token", tokenvalue);
%>--%>

<form action= "<%=request.getcontextpath ()%>/tokenservlet" method= "POST" >

< Input type= "hidden" name= "Token_key" value= "<%= tokenprocessor.getinstance 
		(). Savetoken (Request)%>"/>
<%--<input type= "hidden" name= "token" value=  "<%=tokenvalue%>"/>--%>
	Name: < Input type= "text" name= "name"/> 
	<input type= "Submit" value= "Submit"/>
</form>

Tokenservlet.java

Package COM.XYC;

Import java.io.IOException;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServlet;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;

Import javax.servlet.http.HttpSession;

    public class Tokenservlet extends HttpServlet {private static final long serialversionuid = 1L; protected void DoPost (HttpServletRequest request, httpservletresponse response) throws Servletexception, Ioexc
        eption {try {thread.sleep (2000);
        catch (Interruptedexception e) {e.printstacktrace ();

        } request.setcharacterencoding ("UTF-8");

        /*string name = Request.getparameter ("name");
        HttpSession session = Request.getsession ();
        Object token = Session.getattribute ("token");
        
        String Tokenvalue = Request.getparameter ("token");
        SYSTEM.OUT.PRINTLN (token);
        System.out.println (Tokenvalue); System.out.pRintln ("Name:" + name);
        if (token!= null && token.equals (tokenvalue)) {Session.removeattribute ("token");
            else {response.sendredirect (Request.getcontextpath () + "/token/token.jsp");
        Return
        }*/Boolean valid = Tokenprocessor.getinstance (). Istokenvalid (Request);
        if (valid) {tokenprocessor.getinstance (). Resettoken (Request);
                }else{Response.sendredirect (Request.getcontextpath () + "/token/token.jsp");
        Return
        }//request.getrequestdispatcher (Request.getcontextpath () + "/token/success.jsp"). Forward (Request,response);
    Response.sendredirect (Request.getcontextpath () + "/token/success.jsp"); }

}


JS client avoids form repeat commit


Use session to implement one-time verification code rationale: Repeat with form > in the original form page, Generate a picture of the verification code, while creating a picture, you need to put the string in the picture into the session > in the original form page, define a text field for input validation code
> in target servlet: Get the value of the validation code in the session and form fields > label two values are consistent, if the same, accept the request, and the Sessin domain of the verification code attributes cleared. If inconsistent, return the original form page directly via redirect, prompting the user for "Authenticode error"
Validatecolorservlet.java

Package COM.XYC;
Import Java.awt.Color;
Import Java.awt.Font;
Import Java.awt.Graphics2D;
Import Java.awt.image.BufferedImage;
Import java.io.IOException;

Import Java.util.Random;
Import Javax.imageio.ImageIO;
Import javax.servlet.ServletException;
Import Javax.servlet.ServletOutputStream;
Import Javax.servlet.http.HttpServlet;
Import Javax.servlet.http.HttpServletRequest;

Import Javax.servlet.http.HttpServletResponse;
	
	public class Validatecolorservlet extends HttpServlet {public static final String Check_code_key = "Check_code_key";
	
	Private static final long serialversionuid = 1L;
	Set the width, height, and number of verification codes private int width = 152;
	private int height = 40;
	
	private int codecount = 4;
	
	Authentication code font height private int fontheight = 4; A single character baseline line in the verification code.
	That is, a single character in the verification code is located at the upper-left corner of the verification code (CodeX, Codey) at the position of private int codeX = 0;
	
	private int codey = 0;
	
	The verification code consists of which characters char [] codesequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz23456789". ToCharArray (); Initialize Authenticode graphics Properties Public VOID init () {fontheight = height-2;
		CodeX = width/(codecount + 2);
	Codey = height-4; public void Service (HttpServletRequest request, httpservletresponse response) throws Servletexception, IOException
		{//define an image cache of type BUFFEREDIMAGE.TYPE_INT_BGR type bufferedimage buffimg = null;
	
		buffimg = new BufferedImage (width, height, bufferedimage.type_3byte_bgr);
		Create a graphics2d image graphics2d graphics = null in buffimg;
		
		Graphics = Buffimg.creategraphics ();
		
		Set a color so that the Graphics2D object's subsequent graphics use this color Graphics.setcolor (color.white); Fills a specified rectangle: X-The x-coordinate of the rectangle to be filled; Y-The y-coordinate of the rectangle to be filled; Width-to fill a rectangle;
		
		Height-graphics.fillrect (0, 0, width, height) to fill the rectangle; Create a Font object: name-font name; Style-font-style constants;
		Size-font dot size font font = NULL;
		Font = new Font ("", Font.Bold, Fontheight);
		
		Make the subsequent graphics for the Graphics2D object use this font graphics.setfont (font);
		
		Graphics.setcolor (Color.Black); Draws the border of the specified rectangle, and the drawn rectangle is one higher than the widget width one pixel graphics.drawrect (0, 0, width-1, height- 1);
		Randomly generate 15 interference lines, so that the authentication code in the image is not easily detected by other programs Random Random = null;
		Random = new Random ();
		Graphics.setcolor (Color.green);
			for (int i = 0; i < i++) {int x = random.nextint (width);
			int y = random.nextint (height);
			int x1 = Random.nextint (20);
			int y1 = Random.nextint (20);
		Graphics.drawline (x, y, x + x1, y + y1);
		//Create a Randomcode object to hold the randomly generated verification code so that the user can log in and verify StringBuffer randomcode;
		
		Randomcode = new StringBuffer ();
			for (int i = 0; i < Codecount i++) {//Get randomly generated captcha number String Strrand = null;
			
			Strrand = string.valueof (Codesequence[random.nextint (36)]);
			
			Putting the random characters that are being produced into the StringBuffer randomcode.append (Strrand);
			Using the randomly generated color to draw the verification code into the image Graphics.setcolor (Color.Blue);
		Graphics.DrawString (Strrand, (i + 1) * CodeX, Codey); //Then put the string corresponding to the stringbuffer containing all the random characters into the HttpSession request.getsession (). setattribute (Check_code_key, Randomcode.
		
		ToString ());
		Prohibit image caching Response.setheader ("Pragma", "No-cache"); Response.SetHeader ("Cache-control", "No-cache");
		
		Response.setdateheader ("Expires", 0);
		Output the image to the output stream servletoutputstream SOS = null;
		SOS = Response.getoutputstream (); 
		Imageio.write (buffimg, "JPEG", SOS);
	Sos.close ();
 }
}

Checkcodeservlet.java
Package COM.XYC;
Import java.io.IOException;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServlet;
Import Javax.servlet.http.HttpServletRequest;

Import Javax.servlet.http.HttpServletResponse;

	public class Checkcodeservlet extends HttpServlet {private static final long serialversionuid = 1L;
		
	  protected void DoPost (HttpServletRequest request, httpservletresponse response) throws Servletexception, IOException { 1.
            
            Get request parameter: Check_code_param_name String paramcode = Request.getparameter ("Check_code_param_name"); 2. Gets the value of the Check_code_key property in the session string Sessioncode = (string) request.getsession (). getattribute ("Check_code_ke
            
            Y ");
            System.out.println (Paramcode); 
            
            System.out.println (Sessioncode); 3. Compare it to. See if it is consistent, if the verification code is correct, if inconsistent, indicating that the verification code error if (! Paramcode!= null && paramcode.equals (Sessioncode)) {Request.getsEssion (). setattribute ("message", "Verification code inconsistent!");
                    Response.sendredirect (Request.getcontextpath () + "/check/index.jsp");
            Return
		
	} System.out.println ("Accept request!");
 }

}

index.jsp
<font color= "Red" >
	<%= session.getattribute ("message") = = null? "": Session.getattribute ("message")%>
</font>
<form action= "<%= request.getcontextpath ()% >/checkcodeservlet "method=" Post >
	name: <input type= "text" name= "name"/>
	checkcode: <input Type= "text" name= "Check_code_param_name"/> 
	/ Validatecolorservlet "> 
	<input type=" Submit "value=" Submit "/>
</form>



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.