表單重複提交

一:使用JavaScript來防止表單重複提交javascript

有三種場景:1:在網絡延遲的狀況下讓用戶有時間點擊屢次submit致使重複提交html

  2:表單提交後點擊「刷新」按鈕致使重複提交java

  3:提交後,點擊瀏覽器的後退而後再次提交設計模式

  <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
  <head>
    <title>Form表單</title>
        <script type="text/javascript">
        var isCommitted = false;//表單是否已經提交標識,默認爲false
        function dosubmit(){
            if(isCommitted==false){
                isCommitted = true;//提交表單後,將表單是否已經提交標識設置爲true
                return true;//返回true讓表單正常提交
            }else{
                return false;//返回false那麼表單將不提交
            }
        }
    </script>
  </head>
 
  <body>
      <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" onsubmit="return dosubmit()" method="post">
        用戶名:<input type="text" name="username">
        <input type="submit" value="提交" id="submit">
    </form>
  </body>
</html>瀏覽器

另外一種方式:將提交按鈕設置爲不可用。服務器

  function dosubmit(){
    //獲取表單提交按鈕
    var btnSubmit = document.getElementById("submit");
    //將表單提交按鈕設置爲不可用,這樣就能夠避免用戶再次點擊提交按鈕
    btnSubmit.disabled= "disabled";
    //返回true讓表單能夠正常提交
    return true;
}網絡

js只能解決問題1,可是2,3解決不了。session

利用session解決2和3:在服務器端解決dom

  作法:在服務器端生成一個惟一的隨機標識號,專業術語:Token(令牌)。同時在當前用戶的Session中保存這個Token。而後將Token發送到客戶端的Form表單中jsp

在表單中使用隱藏域來存儲這個Token。表單提交的時候連同這個Token一塊兒提交到服務器端。而後在服務器端判斷客戶端提交上來的Token與服務器生成的是否同樣。不同就是重複提交了,此時服務器就不能夠處理重複提交的表單。處理完後清除當前用戶的Session中存儲的標識號。

  在下列狀況中,服務器程序將拒絕處理

  1:存儲session中的Token與表單提交的Token不一樣。

  2:當前用戶的session中不存在token

  3:用戶提交的表單數據中沒有Token

form.jsp頁面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>
  <head>
   <title>Form表單</title>
 
  </head>
 
  <body>
    <form action="${pageContext.request.contextPath }/demo02" method="post">
    <%--使用EL表達式取出存儲在session中的token--%>
       <input type="hidden" name="token" value="${token}"/>
        用戶名:<input type="text" name="username">
            <input type="submit" value="提交">
    </form>
  </body>
</html>
業務處理

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
     boolean b = isRepeatSubmit(request);//判斷用戶是不是重複提交
              if(b==true){
                   System.out.println("請不要重複提交");
                     return;
                }
                 request.getSession().removeAttribute("token");//移除session中的token
                System.out.println("處理用戶提交請求!!");
           }
            
             /**
              * 判斷客戶端提交上來的令牌和服務器端生成的令牌是否一致
             * @param request
             * @return
            *         true 用戶重複提交了表單
             *         false 用戶沒有重複提交表單
             */
           private boolean isRepeatSubmit(HttpServletRequest request) {
                String client_token = request.getParameter("token");
                //一、若是用戶提交的表單數據中沒有token,則用戶是重複提交了表單
                if(client_token==null){
                    return true;
                }
                //取出存儲在Session中的token
                String server_token = (String) request.getSession().getAttribute("token");
             //二、若是當前用戶的Session中不存在Token(令牌),則用戶是重複提交了表單
                if(server_token==null){
                     return true;
                }
                 //三、存儲在Session中的Token(令牌)與表單提交的Token(令牌)不一樣,則用戶是重複提交了表單
                if(!client_token.equals(server_token)){
                     return true;
                }
                
                return false;
             }

服務器端保存:

protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String token=TokenProccessor.getInstance().makeToken();
        System.out.println("在FormServlet中生成的token:"+token);
        request.getSession().setAttribute("token", token);//在服務器端保存
        request.getRequestDispatcher("/form.jsp").forward(request, response);
    }

生成token的工具類:

/* * 生成Token的工具類 */public class TokenProccessor {    /*     * 單例設計模式(保證類的對象在內存中只有一個)     * 1:把類的構造函數私有     * 2:本身建立一個類的對象     * 3:對外提供一個公共的方法,返回類的對象     */    private TokenProccessor(){}    private static final TokenProccessor instance = new TokenProccessor();    public static TokenProccessor getInstance(){           return instance;        }         public String makeToken(){  //checkException                 //  7346734837483  834u938493493849384  43434384                String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";                 //數據指紋   128位長   16個字節  md5                  try {                     MessageDigest md = MessageDigest.getInstance("md5");                    byte md5[] =  md.digest(token.getBytes());                    //base64編碼--任意二進制編碼明文字符   adfsdfsdfsf                     BASE64Encoder encoder = new BASE64Encoder();                     return encoder.encode(md5);                 } catch (NoSuchAlgorithmException e) {                      throw new RuntimeException(e);                 }             }}

相關文章
相關標籤/搜索