后台防止表单重复提交
Posted myseries
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后台防止表单重复提交相关的知识,希望对你有一定的参考价值。
方案一:利用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>
以上是关于后台防止表单重复提交的主要内容,如果未能解决你的问题,请参考以下文章