JavaWeb 如何防止表單重複提交 - 使用Token,令牌
說到重複提交 ,應該想到兩種場景:
1. 在下單,或者支付 這種情況 那麼不允許 刷新,不允許後退再點擊提交(後退之後提交會失敗,修改了也不行)。
2. 在填寫表單之後,提交完成之後,不允許 刷新,但是允許 返回之後 提交,給用戶修改表單的機會。
解決方法
首先可以防止用戶刷新,處理完成之後用Redirect的方式 跳轉到success頁面,這樣刷新則沒有用。但是返回的時候還可以提交一次緩存的數據。
然後 使用令牌,在頁面表單生成一個token, 這是在請求頁面的時候產生的,放在隱藏域之中。然後把token存在session中。
提交之後,判斷這兩個token是否一樣,是一樣則通過,並且清除session 中的 token,這樣就能防止返回之後再次提交,因爲返回的時候點擊提交讀取的是緩存,但是session已經沒有這個token了。這適用於場景1
對於場景2,直接禁止緩存,那麼返回的時候一定重新請求 表單,用戶可以再次填寫。在用token的情況下,session中的 token總是和 隱藏域中的一致。
在使用令牌的情況下,如果用戶沒有重新請求表單,並且惡意提交之前的Post數據,則在服務器端,session裏面的token已經被清空且沒有重新請求,則session的token爲空不能通過。
- <body>
- <%
- long token=System.currentTimeMillis(); //產生時間戳的token
- session.setAttribute("token",token);
- %>
- <form action="isRepeat" method="post">
- <input type="text" name="username"/>
- <input type="text" name="password"/>
- <input type="hidden" value="<%=token %>" name="Reqtoken"/>
- <input type="submit" value="提交"/>
- </form>
- </body>
- String token = req.getParameter("Reqtoken");
-
- HttpSession session=req.getSession();
- String tokenInSession = ""+session.getAttribute("token");
-
- System.out.println("Session in Token: " + tokenInSession);
- System.out.println("表單的Token:" + token+"\n------------");
-
- if (tokenInSession!=null && token!=null && token.equals(tokenInSession)) {
- resp.getWriter().println("ok ");
- session.removeAttribute("token");
- } else {
-
- System.out.println("重複提交,或者有錯誤");
- resp.sendRedirect("index.jsp");
- return;
- }
-
- resp.sendRedirect("success.jsp");
另一種方法: 該方法原理是 記住上一次提交的 頁面token。將本次的token和上次比對,如果一樣說明重複提交。該方法不需要禁用緩存。
- String token = req.getParameter("Reqtoken");
-
- HttpSession session=req.getSession();
-
- String LasttokenInSession = (String) session.getAttribute("Lasttoken");
-
-
- System.out.println("表單的Token:" + token);
- System.out.println("上一次表單的Token:" + LasttokenInSession);
-
- if(token!=null && (LasttokenInSession ==null || !LasttokenInSession.equals(token)) ) {
-
-
- session.removeAttribute("token");
-
- session.setAttribute("Lasttoken",token);
-
- }
- else {
-
-
- resp.getWriter().println("<h1>表單頁面無效,請返回並且刷新頁面</h1>");
- resp.getWriter().println("<h1><a href=\""+ "index.jsp" +"\">返回並刷新</a></h1>");
-
- resp.getWriter().println("Do not Duplicate submit!");
- return;
- }
-
- resp.sendRedirect("success.jsp");