1.表單的重復提交
①:重復提交情況:在表單提交到一個Servlet,而servlet又通過請求轉發的方式響應一個jsp(html),此時地址欄還是第一次請求servlet的地址欄,在響應頁面刷新時,會出現重復提交。重定向不會
解決方法:不用轉發到另一頁面,采用重定向的方式跳轉到目標頁面
response.sendRedirect(request.getContextPath()+"/background/main.jsp");
②:在提交表單時,如果網速較差,可能會導致點擊提交按鈕多次,這種情況也會導致表單重復提交
解決方法:在提交之后,把按鈕設置為不可以用(js)
<script type="text/javascript"> window.onload = function(){ //獲取按鈕的對象 var btn = document.getElementById("btn"); //為按鈕綁定單擊響應函數 btn.onclick = function(){ //點擊以后使按鈕不可用 this.disabled=true; //當將提交按鈕設置為不可用時,會自動取消它的默認行為 //手動提交表單 this.parentNode.submit(); }; }; </script>
......
<input type="submit" value="提交" id="btn">
③:表單提交成功以后,直接點擊瀏覽器上回退按鈕,不刷新頁面,然后點擊提交按鈕再次提交表單
解決方法:在jsp中加入一個標記
reg.jsp:
<%@page import="java.util.UUID"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <% //java代碼 //隨機出現一個令牌,轉成String,並且去除其中的“-” String uuid = UUID.randomUUID().toString().replace("-", ""); // 把生成的令牌放到session域中 session.setAttribute("token1", uuid); %> <body> <form action="regServlet" method="post"> <input type="hidden" name="token" value="<%=uuid%>"/> 用戶名:<input type="text" name="name"><br> 密 碼: <input type="password" name="pwd"><br> <input type="submit" value="注冊"> </form> </body> </html>
RegServlet.java
package com.hpe.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/regServlet") public class RegServlet extends HttpServlet { private static final long serialVersionUID = 1L; public RegServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); // 獲取用戶請求參數 // 獲取reg中token令牌,防止用戶重復提交 // 獲取<input>標簽中的令牌 String token = request.getParameter("token"); // 獲取session中令牌 String token1 = (String) request.getSession().getAttribute("token1"); //兩個令牌判斷,相等的話:相當於注冊成功,清除session中的令牌, // 因為注冊成功之后,session中清空,兩個令牌不相等,所以判斷為重復提交 if (token.equals(token1)) { System.out.println("注冊成功"); request.getSession().removeAttribute("token1"); // 請求轉發——一般用在request數據共享(setAttribute) // 會產生重復提交---為什么 // 轉發地址欄沒變,還是regServlet,刷新一次相當於重新請求了一次regServlet,再執行了一次 request.getRequestDispatcher("/index.jsp").forward(request, response); } else { System.out.println("注冊失敗,重復提交"); request.getRequestDispatcher("/index.jsp").forward(request, response); } // 把參數賦值給實體類屬性 // 調用service方法 // 判斷是否注冊成功 } }
表單重復提交的危害:
- 向數據庫中插入大量的重復且沒有意義的數據,占用服務器的資源
- 處理請求服務器並沒有檢查請求是否為重復的請求,導致惡意的攻擊
2.不是重復提交的情況
①:注冊成功,點擊后退,刷新原來的表單頁面,不是重復提交
因為,在注冊頁面刷新,相當於重新注冊一個新用戶。