• 客户端服务端防止用户重复提交表单


    一、什么是表单重复提交?
    当网络有延迟时,用户提交的表单等数据还没有完成此次提交,但用户又多次点击提交,造成用户数据在数据库或存储中被提交多次。
    利用线程延迟,简单模拟重复提交。
    表单页面为form.html
    [html] view plain copy



    form.html

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
    <meta http-equiv="description" content="this is my page">  
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->  
    



    用户名 :



    处理提交请求的servlet为DoFormServlet.java
    [java] view plain copy
    package SessionDemo;

    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)  
        {  
            e.printStackTrace();  
        }  
        System.out.println("向数据库中注册数据。");  
    }  
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException  
    {  
        doGet(request, response);  
    }  
    

    }
    在浏览器中加载form.html

    当用户反复点击“提交”时,就造成了重复提交。

    二、解决方法一:利用javascript阻止
    其他不变,将form.html修改为
    [html] view plain copy



    form.html

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
    <meta http-equiv="description" content="this is my page">  
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->  
    


    var isCommitted = false;
    function dosubmit()
    {
    if(!isCommitted)
    {
    isCommitted=true;
    return true;
    }
    else
    {
    return false;
    }
    }




    用户名 :




    这样在浏览器中加载form.html后,点击“提交”,终端中只会输出一次”向数据库中注册数据。”,表明成功阻止表单反复提交。
    以上form.html可以进一步优化,当用户点击“提交”后,“提交”按钮应该变为灰色不可用。
    [html] view plain copy



    form.html

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
    <meta http-equiv="description" content="this is my page">  
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->  
    


    function dosubmit()
    {
    var input = document.getElementById("submit");
    input.disabled = 'disabled';
    return true;
    }




    用户名 :




    利用javascript的方法不能完全防止用户恶意重复提交,例如:用户可以将form.html保存后修改,还可以在点击“提交”后重复刷新页面,从而实现反复提交。
    三、解决方法二:利用服务器端Session防止表单重复提交。
    其中FormServlet.java为
    [java] view plain copy
    package SessionDemo;

    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
    {
    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编码防止乱码。  
            BASE64Encoder encoder = new BASE64Encoder();  
            return encoder.encode(md5);  
        } catch (NoSuchAlgorithmException e)  
        {  
            throw new RuntimeException(e);  
        }  
    }  
    

    }
    添加form.jsp
    [plain] view plain copy
    <%@ page language=”java” import=”java.util.*” pageEncoding=”UTF-8”%>







    用户名




    将DoFormServlet.java修改为
    [java] view plain copy
    package SessionDemo;

    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");  
    
        boolean b = isTokenValue(request);  
        if (!b)  
        {  
            System.out.println("请不要重复提交。");  
            return;  
        }  
    
        request.getSession().removeAttribute("token");  
        System.out.println("向数据库中注册数据。");  
    }  
    
    //判断表单号是否有效  
    private boolean isTokenValue(HttpServletRequest request)  
    {  
        String clientToken = request.getParameter("token");  
        if(clientToken==null)  
        {  
            return false;  
        }  
    
        String serverToken = (String) request.getSession().getAttribute("token");  
        if(serverToken==null)  
        {  
            return false;  
        }  
    
        if (!clientToken.equals(serverToken))  
        {  
            return false;  
        }  
    
        return true;  
    }  
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException  
    {  
        doGet(request, response);  
    }  
    

    }
    再浏览器中加载FormServlet

    点击“提交”后跳转

    终端显示用户提交

    这时即使用户点击“刷新”,也不能实现重复提交。

  • 相关阅读:
    react中refs的使用
    在npm发布自己造的轮子
    如何阅读一本书——分析阅读模板
    如何阅读一本书——检视阅读模板
    Redis教程——检视阅读
    如何阅读一本书——分析阅读Pre
    SVN常用功能介绍(二)
    SVN常用功能介绍(一)
    分页sql大全
    .NetCore 登录(密码盐+随机数)
  • 原文地址:https://www.cnblogs.com/sean-zeng/p/11024785.html
Copyright © 2020-2023  润新知