后台防止表单重复提交

匿名 (未验证) 提交于 2019-12-02 23:32:01

方案一:利用Session防止表单重复提交

具体的做法:
  1、获取用户填写用户名和密码的页面时向后台发送一次请求,这时后台会生成唯一的随机标识号,专业术语称为Token(令牌)。

  2、将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端。

  3、服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

看具体的范例:

  1.创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面

import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;     public class FormServlet extends HttpServlet {     private static final long serialVersionUID = -884689940866074733L;       public void doGet(HttpServletRequest request, HttpServletResponse response)              throws ServletException, IOException {           String token =  UUID.randomUUID().toString() ;//创建令牌         System.out.println("在FormServlet中生成的token:"+token);          request.getSession().setAttribute("token", token);  //在服务器使用session保存token(令牌)          request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面      }        public void doPost(HttpServletRequest request, HttpServletResponse response)              throws ServletException, IOException {          doGet(request, response);      }   }

  2.在form.jsp中使用隐藏域来存储Token(令牌)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">   <html>   <head>   <title>form表单</title>   </head>      <body>       <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" method="post">          <%--使用隐藏域存储生成的token--%>          <%--              <input type="hidden" name="token" value="<%=session.getAttribute("token") %>">          --%>          <%--使用EL表达式取出存储在session中的token--%>          <input type="hidden" name="token" value="${token}"/>           用户名:<input type="text" name="username">           <input type="submit" value="提交">      </form>  </body>  </html>

  3.DoFormServlet处理表单提交 

import java.io.IOException;   import javax.servlet.ServletException;   import javax.servlet.http.HttpServlet;   import javax.servlet.http.HttpServletRequest;   import javax.servlet.http.HttpServletResponse;      public class DoFormServlet extends HttpServlet {        public void doGet(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");              //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单              if(client_token==null){                  return true;              }              //取出存储在Session中的token              String server_token = (String) request.getSession().getAttribute("token");              //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单              if(server_token==null){                 return true;              }              //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单              if(!client_token.equals(server_token)){                  return true;              }                            return false;          }        public void doPost(HttpServletRequest request, HttpServletResponse response)              throws ServletException, IOException {          doGet(request, response);      }    }

方案二:判断请求url和数据是否和上一次相同

  推荐,非常简单,页面不需要任何传入,只需要在验证的controller方法上写上自定义注解即可

  写好自定义注解

import java.lang.annotation.ElementType;   import java.lang.annotation.Retention;   import java.lang.annotation.RetentionPolicy;   import java.lang.annotation.Target;      /**   * 一个用户 相同url 同时提交 相同数据 验证   * @author Administrator   *   */   @Target(ElementType.METHOD)   @Retention(RetentionPolicy.RUNTIME)   public @interface SameUrlData {             }  

  写好拦截器

import java.lang.reflect.Method;   import java.util.HashMap;   import java.util.Map;      import javax.servlet.http.HttpServletRequest;   import javax.servlet.http.HttpServletResponse;      import org.springframework.web.method.HandlerMethod;   import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;      import com.thinkgem.jeesite.common.mapper.JsonMapper;      /**   * 一个用户 相同url 同时提交 相同数据 验证   * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单   * @author Administrator   *   */   public class SameUrlDataInterceptor  extends HandlerInterceptorAdapter{                @Override           public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {               if (handler instanceof HandlerMethod) {                   HandlerMethod handlerMethod = (HandlerMethod) handler;                   Method method = handlerMethod.getMethod();                   SameUrlData annotation = method.getAnnotation(SameUrlData.class);                   if (annotation != null) {                       if(repeatDataValidator(request))//如果重复相同数据                           return false;                       else                            return true;                   }                   return true;               } else {                   return super.preHandle(request, response, handler);               }           }       /**       * 验证同一个url数据是否相同提交  ,相同返回true       * @param httpServletRequest       * @return       */       public boolean repeatDataValidator(HttpServletRequest httpServletRequest)       {           String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());           String url=httpServletRequest.getRequestURI();           Map<String,String> map=new HashMap<String,String>();           map.put(url, params);           String nowUrlParams=map.toString();//                      Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");           if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面           {               httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);               return false;           }           else//否则,已经访问过页面           {               if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据               {                                      return true;               }               else//如果上次 url+数据 和本次url加数据不同,则不是重复提交               {                   httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);                   return false;               }                          }       }      }  
<mvc:interceptor>        <mvc:mapping path="/**"/>        <bean class="*.*.SameUrlDataInterceptor"/>   </mvc:interceptor>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!