表单重复提交--->使用Session防止表单重复提交

  表单重复提交一般情况下有3种场景:

  1> 网络延迟时,不断点击submit按钮

  2> 表单提交后,用户点击刷新

  3> 表单提交后,用户返回表单页面重新提交

        针对这三种场景,在网上查阅各种方案后,感觉以下方案能够比较好的解决问题

第一种:

  javascript方案 (只能用于第一种场景):

	<form action = "doForm" id ="f" method = "post" >
		<input type = "text" name= "username" autocomplete = "off"/>
		<input type = "submit" id = "submit" value="提交" onclick = "checkSubmit()">
	</form> 

  在js 中只要有标记变化就可以,可以使boolean,也可以是数值 

        var submitFlag = false;
	function checkSubmit(){
		alert(submitFlag);
		if(!submitFlag){
			submitFlag = true;
			return true;
		}
		return false;
	}

第二种:

  在表单提交后,将按钮设为不可用(只适用于第一种场景):

 function checkSubmit(){
        document.getElementById("submit").disabled = "disabled";
        return true;
 } 

第三种:场景二 和 场景三 在客户端没办法解决,只能依赖服务器端解决,而此时就要用session了

  具体方法:在服务器端生成一个标记号:Token(令牌)。发送到客户端,客户端将其保存在一个隐藏域中,表单提交时将隐藏域一起提交,在服务器端 对token进行比较,如果相同,说明是一次提交,处理完成后将session中的token删除;如果不同,说明是重复提交. 以下是相关源代码:

令牌生成类:
package com.rcj.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import sun.misc.BASE64Encoder;

/**
 * 
 * @author Mars
 * Time:2017年9月29日
 *
 */
public class TokenProccessor {

    //单例设计模式
    private TokenProccessor() {};
    private static TokenProccessor tp = new TokenProccessor();
    public static TokenProccessor getInstance() {
        return tp;
    }
    
    /**
     * 生成Token
     * 
     */
    public String makeToken() {
        String token = (System.currentTimeMillis()+new Random().nextInt(999999999))+"";
        //数据指纹
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("md5");
            byte[] md5 = md.digest(token.getBytes());
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

}

 

插入令牌servlet类
/**
 * 
 * @author Mars
 * Time:2017年9月29日
 *
 */
public class FormServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String token = TokenProccessor.getInstance().makeToken();
        req.getSession().setAttribute("token", token);
        req.getRequestDispatcher("/resubmit.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(req, resp);
    }
    
}

 

form 表单:
<%--使用隐藏域存储生成的token--%>
    <form action = "doForm" id ="f" method = "post" >
        <input type = "text" style="display:none" name = "token" value = "${token}"> 
        <input type = "text" name= "username" autocomplete = "off"/>
        <input type = "submit" id = "submit" value="提交" onclick = "checkSubmit()">
    </form> 数据提交处理servlet类:package com.rcj.servlet;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 
 * @author Mars
 * Time:2017年9月29日
 *
 */
public class DoFormServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        req.setCharacterEncoding("utf8");
        boolean b = isRepeatSubmit(req);
        if(b == true) {
            System.out.println("请不要重复提交");
            return ;
        }
        req.getSession().removeAttribute("token");
        String username = req.getParameter("username");
        System.out.println("数据库添加:"+username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(req, resp);
    }

    /**
     * 判断客户端提交上的令牌和服务器端是否一致
     * true  用户重复提交了表单
     * false 用户没有重复提交表单
     */
    private boolean isRepeatSubmit(HttpServletRequest  request) {
        
        try {
            String client_token = request.getParameter("token");
            if(client_token == null) {
                return true;
            }
String server_token
= request.getSession().getAttribute("token").toString(); if(request.getSession().getAttribute("token").toString() == null) { return true; } if(!client_token.equals(server_token)) { return true; } } catch (Exception e) { return true; } return false; } }

 

posted @ 2017-09-30 10:18  执着的蚂蚁  阅读(762)  评论(0编辑  收藏  举报