zoukankan      html  css  js  c++  java
  • 防止表单重复提交

    一:在客户端通过javascript防止表单重复提交

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <title>form.html</title>
     5     <meta name="keywords" content="keyword1,keyword2,keyword3">
     6     <meta name="description" content="this is my page">
     7     <meta name="content-type" content="text/html; charset=UTF-8">
     8 <script type="text/javascript">
     9               var isCommitted = false;
    10               function doSubmit()
    11               {
    12                   if(isCommitted==false){
    13                       isCommitted = true;
    14                       return true;
    15                   }
    16                   return false;
    17               }
    18 
    19 </script>
    20   </head>
    21   <body>
    22   <form action="/test/servlet/FormServlet" method="post"  onsubmit="return dosubmit()">
    23   用户名:<input type="text" name="username"/>
    24   <br>
    25   <input type="submit" value="提交">
    26   </form>
    27  <br>
    28   </body>
    29 </html>

    还可以提交过后将提交按钮变灰,无法提交

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <title>form.html</title>
     5     <meta name="keywords" content="keyword1,keyword2,keyword3">
     6     <meta name="description" content="this is my page">
     7     <meta name="content-type" content="text/html; charset=UTF-8">
     8 <script type="text/javascript">
     9 function dosubmit(){
    10     var submit = document.getElementById("submit");
    11     submit.disabled= "disabled";
    12     return true;
    13 
    14 }
    15 </script>
    16   </head>
    17   <body>
    18   <form action="/test/servlet/FormServlet" method="post"  onsubmit="return dosubmit()">
    19   用户名:<input type="text" name="username"/>
    20   <br>
    21   <input type="submit" value="提交"  id="submit">
    22   </form>
    23  <br>
    24   </body>
    25 </html>

    其实只在前台用javascript是禁不掉恶意用户的恶意操作的,必须在服务端处理。如用户单击”刷新”,或单击”后退”再次提交表单,将导致表单重复提交。但在服务端处理的同时,客户端也要处理,因为javascript最大的好处就是提升用户体验。

    二利用session防止表单重复提交

    表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
    当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
    在下列情况下,服务器程序将拒绝用户提交的表单请求:
    存储Session域中的表单标识号与表单提交的标识号不同
    当前用户的Session中不存在表单标识号
    用户提交的表单数据中没有标识号字段
     1 package cn.itcast.form;
     2 
     3 import java.io.IOException;
     4 import java.io.PrintWriter;
     5 import java.security.MessageDigest;
     6 import java.security.NoSuchAlgorithmException;
     7 import java.util.Random;
     8 
     9 import javax.servlet.ServletException;
    10 import javax.servlet.http.HttpServlet;
    11 import javax.servlet.http.HttpServletRequest;
    12 import javax.servlet.http.HttpServletResponse;
    13 
    14 import sun.misc.BASE64Encoder;
    15 
    16 //负责产生表单
    17 public class FormServlet extends HttpServlet {
    18 
    19     public void doGet(HttpServletRequest request, HttpServletResponse response)
    20             throws ServletException, IOException {
    21 
    22         response.setContentType("text/html;charset=UTF-8");
    23         PrintWriter out = response.getWriter();
    24         
    25         String token = TokenProccessor.getInstance().makeToken();
    26         request.getSession().setAttribute("token", token);  //在服务器端保存随机数
    27         
    28         out.println("<form action='/day07/servlet/DoFormServlet' method='post'>");
    29             out.write("<input type='hidden' name='token' value='"+token+"'>");
    30             out.println("用户名:<input type='text' name='username'>");
    31             out.println("<input type='submit' value='提交'>");
    32         out.println("</form>");
    33     }
    34 
    35     public void doPost(HttpServletRequest request, HttpServletResponse response)
    36             throws ServletException, IOException {
    37 
    38         doGet(request, response);
    39     }
    40 }
    41 //工具类生成表单标识号
    42 class TokenProccessor{
    43     
    44     /*
    45      *单态设计模式(保证类的对象在内存中只有一个)
    46      *1、把类的构造函数私有
    47      *2、自己创建一个类的对象
    48      *3、对外提供一个公共的方法,返回类的对象
    49      * 
    50      */
    51     private TokenProccessor(){}
    52     
    53     private static final TokenProccessor instance = new TokenProccessor();
    54     
    55     public static TokenProccessor getInstance(){
    56         return instance;
    57     }
    58     
    59     
    60     public String makeToken(){  //checkException
    61         
    62         //  7346734837483  834u938493493849384  43434384
    63         String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
    64         //产生固定长度的随机数
    65         //数据指纹   128位长   16个字节  md5
    66         try {
    67             MessageDigest md = MessageDigest.getInstance("md5");
    68             byte md5[] =  md.digest(token.getBytes());
    69             
    70             //base64编码--任意二进制编码明文字符   
    71             BASE64Encoder encoder = new BASE64Encoder();
    72             return encoder.encode(md5);
    73             
    74         } catch (NoSuchAlgorithmException e) {
    75             throw new RuntimeException(e);
    76         }
    77         
    78     }
    79     
    80 }
     1 package cn.itcast.form;
     2 
     3 import java.io.IOException;
     4 import java.io.PrintWriter;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.http.HttpServlet;
     8 import javax.servlet.http.HttpServletRequest;
     9 import javax.servlet.http.HttpServletResponse;
    10 
    11 public class DoFormServlet extends HttpServlet {
    12 
    13     public void doGet(HttpServletRequest request, HttpServletResponse response)
    14             throws ServletException, IOException {
    15 
    16         
    17         boolean b = isToken(request);  //判断用户是否是重复提交
    18         if(b==true){
    19             System.out.println("请不要重复提交");
    20             return;
    21         }
    22         
    23         request.getSession().removeAttribute("token");
    24         //移除session中的随机数
    25         System.out.println("处理用户提交请求!!");
    26         
    27     }
    28 
    29     private boolean isToken(HttpServletRequest request) {
    30         
    31         String client_token = request.getParameter("token");//客户机带过来的随机数
    32         //没有带随机数过来,说明是恶意用户用自己的form提交到服务端
    33         if(client_token==null){
    34             return true;
    35         }
    36         //带了随机数过来,考察服务器保存的随机数
    37         String server_token = (String) request.getSession().getAttribute("token");
    38         //服务器没有保存随机数,说明服务器处理过这个表单,处理表单后,将session中的这个随机数移除了
    39         if(server_token==null){
    40             return true;
    41         }
    42         //用户带过来的随机数和服务器存的不一样,说明是恶意提交
    43         if(!client_token.equals(server_token)){
    44             return true;
    45         }
    46         //正常提交
    47         return false;
    48     }
    49 
    50     public void doPost(HttpServletRequest request, HttpServletResponse response)
    51             throws ServletException, IOException {
    52 
    53         doGet(request, response);
    54     }
    55 
    56 }
  • 相关阅读:
    使用FolderBrowserDialog组件选择文件夹
    使用OpenFileDialog组件打开多个文
    使用OpenFileDialog组件打开对话框
    获取弹出对话框的相关返回值
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1137 Final Grading (25 分)
    PAT 甲级 1137 Final Grading (25 分)
  • 原文地址:https://www.cnblogs.com/yyz666/p/4061805.html
Copyright © 2011-2022 走看看