zoukankan      html  css  js  c++  java
  • 表单重复提交--->使用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; } }
  • 相关阅读:
    iOS 打电话 发邮件
    iOS
    varchar(50)能存50个汉字
    CSS 内联元素
    mysql修改用户密码的方法
    PHP error_reporting(0)
    索引数组和关联数组
    ubuntu文件夹右键没有共享选项
    Ubuntu安装samba的问题
    安卓.开发规范(高级)
  • 原文地址:https://www.cnblogs.com/rcjs/p/7613899.html
Copyright © 2011-2022 走看看