防止重複提交 令牌法

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

說到重複提交 ,應該想到兩種場景:
1. 在下單,或者支付 這種情況 那麼不允許  刷新,不允許後退再點擊提交(後退之後提交會失敗,修改了也不行)。
2. 在填寫表單之後,提交完成之後,不允許 刷新,但是允許 返回之後 提交,給用戶修改表單的機會。



解決方法

首先可以防止用戶刷新,處理完成之後用Redirect的方式 跳轉到success頁面,這樣刷新則沒有用。但是返回的時候還可以提交一次緩存的數據。

然後 使用令牌,在頁面表單生成一個token, 這是在請求頁面的時候產生的,放在隱藏域之中。然後把token存在session中。
提交之後,判斷這兩個token是否一樣,是一樣則通過,並且清除session 中的 token,這樣就能防止返回之後再次提交,因爲返回的時候點擊提交讀取的是緩存,但是session已經沒有這個token了。這適用於場景1

對於場景2,直接禁止緩存,那麼返回的時候一定重新請求 表單,用戶可以再次填寫。在用token的情況下,session中的 token總是和 隱藏域中的一致。

在使用令牌的情況下,如果用戶沒有重新請求表單,並且惡意提交之前的Post數據,則在服務器端,session裏面的token已經被清空且沒有重新請求,則session的token爲空不能通過。

  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>  


  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和上次比對,如果一樣說明重複提交。該方法不需要禁用緩存。


  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"); //此句子導致刷新無效  




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章