解决表单重复提交1

来源:互联网 发布:响应式网站推荐知乎 编辑:程序博客网 时间:2024/06/03 22:39

JavaWeb 如何防止表单重复提交 - 使用Token,令牌

说到重复提交 ,应该想到两种场景:
1. 在下单,或者支付 这种情况 那么不允许  刷新,不允许后退再点击提交(后退之后提交会失败,修改了也不行)。
2. 在填写表单之后,提交完成之后,不允许 刷新,但是允许 返回之后 提交,给用户修改表单的机会。



解决方法

首先可以防止用户刷新,处理完成之后用Redirect的方式 跳转到success页面,这样刷新则没有用。但是返回的时候还可以提交一次缓存的数据。

然后 使用令牌,在页面表单生成一个token, 这是在请求页面的时候产生的,放在隐藏域之中。然后把token存在session中。
提交之后,判断这两个token是否一样,是一样则通过,并且清除session 中的 token,这样就能防止返回之后再次提交,因为返回的时候点击提交读取的是缓存,但是session已经没有这个token了。这适用于场景1

对于场景2,直接禁止缓存,那么返回的时候一定重新请求 表单,用户可以再次填写。在用token的情况下,session中的 token总是和 隐藏域中的一致。
===============================================================

在使用令牌的情况下,如果用户没有重新请求表单,并且恶意提交之前的Post数据,则在服务器端,session里面的token已经被清空且没有重新请求,则session的token为空不能通过。

[html] view plain copy
  1. <body>  
  2.     <%  
  3.            long token=System.currentTimeMillis();    //产生时间戳的token  
  4.             session.setAttribute("token",token);      
  5.     %>  
  6.     <form  action="isRepeat" method="post">  
  7.         <input type="text"  name="username"/>  
  8.         <input type="text"  name="password"/>  
  9.         <input type="hidden" value="<%=token %>" name="Reqtoken"/>   <!-- 作为hidden提交 -->  
  10.         <input type="submit" value="提交"/>  
  11.     </form>  
  12. </body>  


[java] view plain copy
  1. String token = req.getParameter("Reqtoken");// 获取表单上面的时间戳T1  
  2.           
  3.         HttpSession session=req.getSession();  
  4.         String tokenInSession  =  ""+session.getAttribute("token");  
  5.           
  6.         System.out.println("Session in Token: " + tokenInSession);  
  7.         System.out.println("表单的Token:" + token+"\n------------");  
  8.   
  9.         if (tokenInSession!=null && token!=null && token.equals(tokenInSession)) {   
  10.             resp.getWriter().println("ok ");  
  11.             session.removeAttribute("token");  
  12.         } else { //如果禁止缓存,返回会 重新请求,tokenInSession  是不会为空的  
  13.               
  14.             System.out.println("重复提交,或者有错误");//或者有错误,直接访问servlet等  
  15.             resp.sendRedirect("index.jsp");  
  16.             return;  
  17.         }  
  18.   
  19.         resp.sendRedirect("success.jsp"); //此句子导致刷新无效  


禁止缓存的方法,参见另一篇




另一种方法: 该方法原理是 记住上一次提交的 页面token。将本次的token和上次比对,如果一样说明重复提交。该方法不需要禁用缓存。


[java] view plain copy
  1.               String token = req.getParameter("Reqtoken");// 获取表单上面的时间戳  
  2.   
  3. HttpSession session=req.getSession();  
  4.   
  5. String LasttokenInSession  =  (String) session.getAttribute("Lasttoken");  
  6.   
  7. //System.out.println("------------\nToken in Session: " + tokenInSession);  
  8. System.out.println("表单的Token:" + token);  
  9. System.out.println("上一次表单的Token:" + LasttokenInSession);  
  10. //token!=null 是防止用户直接打开本servlet页面。LasttokenInSession是空,说明是第一次提交 ,和上一次不想等则说明不是重复提交  
  11. if(token!=null && (LasttokenInSession ==null || !LasttokenInSession.equals(token)) ) {  
  12.   
  13.       
  14.     session.removeAttribute("token");//Token 清空  
  15.       
  16.     session.setAttribute("Lasttoken",token);// 保存上一次  
  17.       
  18. }  
  19. else {   
  20.       
  21.   
  22.         resp.getWriter().println("<h1>表单页面无效,请返回并且刷新页面</h1>");  
  23.         resp.getWriter().println("<h1><a href=\"""index.jsp" +"\">返回并刷新</a></h1>");  
  24.       
  25.     resp.getWriter().println("Do not Duplicate submit!");  
  26.     return;  
  27. }  
  28.   
  29. resp.sendRedirect("success.jsp"); //此句子导致刷新无效  

0 0