1. 程式人生 > >利用session防止表單重複提交

利用session防止表單重複提交

使用者在提交表單的過程中,由於網路等原因,可能重複點選提交按鈕,向資料庫重複寫入或者讀取資料,為了防止這種情況發生。

 

解決方式:

1.客戶端防表單重複提交,在前端使用javascript限制。但是在前端並不能完全限制,比如下網頁原始碼更改,重複重新整理等。

2.服務端防止表單重複提交,在servlet中限制。

a.由程式產生表單

程式生成一個token值通過session儲存

package cn.cast.session;

import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sun.misc.BASE64Encoder;

//程式產生表單 
public class FormServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//產生一個隨機數(表單號)
		TokenProcessor tp = TokenProcessor.GetInstance();
		String token = tp.generateToken();
		request.getSession().setAttribute("token", token);
		
		request.getRequestDispatcher("/form.jsp").forward(request, response);
		
		
		
	}


	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

class TokenProcessor{  //產生一個令牌 
	//單例 
	/*1構造方法私有 
	2自己建立一個
	3對外暴露一個方法,允許獲取建立的物件 */
	
	private TokenProcessor(){};
	private static final TokenProcessor instance = new TokenProcessor();
	public static TokenProcessor GetInstance(){
		return instance;
	}
	
	public String generateToken(){
		String Token = System.currentTimeMillis() + new Random().nextInt() +"";
		
		try {
			MessageDigest md = MessageDigest.getInstance("md5");
			byte[] md5 = md.digest(Token.getBytes());
			
			//base64編碼  任何資料經過base64編碼 都會成為鍵盤上能夠找到的明文字元 
			BASE64Encoder enoder = new BASE64Encoder();
			return enoder.encode(md5);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
		
	}
	
}

 jsp網頁中通過表單儲存一個token值 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    
    <title>My JSP 'form.jsp' starting page</title>

  </head>
  
  <body>
    <form action="/web2/servlet/DoFormServlet" method="post">
    <input type="hidden" name="token" value="${token }">
             使用者名稱:<input type="text" name="username">
         <input type="submit" value="提交">
    </form>
  </body>
</html>

處理表單。

package cn.cast.session;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


//處理表單提交請求  
public class DoFormServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		/*String username = request.getParameter("username");
		try {
			Thread.sleep(1000*3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("向資料庫註冊");
	}*/
		
		boolean b = isTokenValid(request);
		
		
		if(!b){
			System.out.println("請不要重複提交");
			return;
			
		}
		request.getSession().removeAttribute("token");
		System.out.println("向資料庫註冊");
	}
	//判斷表單號是否有效;
	private boolean isTokenValid(HttpServletRequest request){
		String client_token = request.getParameter("token");
		if(client_token==null){
			return false;
		}
		String server_token = (String) request.getSession().getAttribute("token");
		if(server_token ==null){
			return false;
			
		}
		if(!client_token.equals(server_token)){
			return false;
		}
		return true;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}