使用session防止表單進行重復提交
阿新 • • 發佈:2018-05-18
dig exc ati ges nproc 其他 延遲 odi 網絡
我們都知道可以通過js的方法來實現防止表單重復提交,但是js只適用於“在網絡延遲的情況下讓用戶有時間點擊多次submit按鈕導致表單重復提交” 的情況下進行操作,
那如果碰到“表單提交後用戶點擊【刷新】按鈕導致表單重復提交”和“用戶提交表單後,點擊瀏覽器的【後退】按鈕回退到表單頁面後進行再次提交”的場景下JS就顯得心有余而力不足了,這個時候我們可以通過java當中生成token驗證token來實現防止表單提交;
先看一下我的項目結構:
我們用到的只有這四個頁面,其他的可以忽略
首先先來看一下創建token的servlet,tokenDemo.java:
package session; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "TokenDemo",urlPatterns = {"/session/TokenDemo"}) public class TokenDemo extends HttpServlet { private static final long serialVersionUID = -884689940866074733L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String token = TokenProccessor .getInstance().makeToken();//創建令牌 // System.out.print("生成的令牌token是"+token); request.getSession().setAttribute("token",token); //存到session裏面 request.getRequestDispatcher("/token.jsp").forward(request,response); } }
這裏面有一個生成token的類,叫做TokenProccessor,接下來我們看看token是怎麽生成的,
TokenProccessor .java:
package session; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; import sun.misc.BASE64Encoder; public class TokenProccessor { private TokenProccessor() {} ; private static final TokenProccessor instance = new TokenProccessor(); public static TokenProccessor getInstance() { return instance; } //生成token public String makeToken(){ String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + ""; try{ MessageDigest md = MessageDigest.getInstance("md5"); byte md5[] = md.digest(token.getBytes()); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(md5); }catch(NoSuchAlgorithmException e){ throw new RuntimeException(e); } } }
好,我們現在有了token,我們可以在頁面上去使用它:token.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>token</title> </head> <body> <form action="${pageContext.request.contextPath}/session/ResultToken" method="post"> <%--使用隱藏存儲生成token--%> <input type="hidden" name="token" value="${token}"> 用戶名:<input type="text" name="username"> <input type="submit" value="提交"> </form> </body> </html>
我們接下來應該幹嘛呢,對,當然是要進行表單的驗證啦,resultToken.java:
package session; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "ResultToken", urlPatterns = {"/session/ResultToken"}) public class ResultToken extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=utf-8"); boolean b = isRepeatSubmit(request); //判斷用戶是否重復提交; if (b == true) { response.getWriter().println("請不要重復提交"); return; } request.getSession().removeAttribute("token"); response.getWriter().println("處理用戶提交請求"); } /*** * 判斷用戶提交上來的token和服務器生成的token是否一致 * 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.equals(client_token)) { return true; } return false; } }
ok,記得寫完servlet的時候必須要去web.xml配置一下,不然取不到路徑。所有的登錄都需要來驗證token。
使用session防止表單進行重復提交