防止form表单重复提交的X种方法 |
您所在的位置:网站首页 › web表单提交的方法 › 防止form表单重复提交的X种方法 |
Form表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如: (1)点击提交按钮两次。 (2)点击刷新按钮。 (3)使用浏览器后退按钮重复之前的操作,导致重复提交表单。 (4)使用浏览器历史记录重复提交表单。 (5)浏览器重复的HTTP请求。 (6)用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交。 参考网友建议和自己的体会,收集了以下几种有效防止表单重复提交的方法:
一、用Javascript禁掉提交按钮 表单提交之后,用JS置灰submit按钮,可防止心急用户重复点击提交按钮。 示例代码如下: //设置disabed属性 $("input[type='submit']").attr("disabled",true); 或者 $("input[type='submit']").attr("disabled","disabled"); //移除disabed属性 $("input[type='submit']").attr("disabled",false); 或者 $("input[type='submit']").attr("disabled","");如果客户端禁用JS,这种方法就会失效。
二、在数据库里添加唯一约束 在数据库里添加唯一约束或创建唯一索引,防止出现重复数据。这是最有效的防止重复提交数据的方法。 //创建表时创建唯一性约束 //在mysql中添加唯一约束: CREATE TABLE `T_User` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(18) NOT NULL unique, `password` varchar(18) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1018 DEFAULT CHARSET=gbk; //在oracle中添加唯一约束: create table `T_User` ( `id` number not null, `username` varchar2(50), `password` varchar2(50), CONSTRAINT tb_user_u1 UNIQUE (`id`) );
三、用Post-Redirect-Get(PRG)模式 1、用sendRedirect()函数转向 用户提交表单之后,执行重定向,转到成功信息页面。可避免用户按F5刷新页面和点击浏览器前进或后退导致的重复提交。 示例代码如下: public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{ response.setContentType("text/html; "); response.sendRedirect("/success.jsp"); }2、用forward()函数转向 除此之外,当用户提交表单,服务器端调用forward()方法,转发到其他页面。 示例代码如下: public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{ response.setContentType("text/html; charset=utf-8"); ServletContext sc = getServletContext(); sc.getRequestDispatcher("/success.jsp").forward(request, response); }
四、用Session防止表单重复提交 具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。 在下列情况下,服务器程序将拒绝处理用户提交的表单请求: (1)存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。 (2)当前用户的Session中不存在Token(令牌)。 (3)用户提交的表单数据中没有Token(令牌)。 示例代码如下: 1、创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面 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(令牌) form表单 --%> 用户名:3、DoFormServlet处理表单提交 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); } }详情参考:http://www.cnblogs.com/xdp-gacl/p/3859416.html
五、用Struts2的token机制 Struts2中的token标签可以用来生成一个唯一的标记,这个标记必须嵌套在form标签内使用,它将在form表单里插入一个隐藏字段并把标记保存到Session中。 示例代码如下: 1、在struts.xml里面需要进行如下配置: /success.jsp /input.jsp2、在需要提交的jsp页面加上标签 (要使用token机制,必须使用struts2提供的标签库) name : password :详情参考:https://blog.csdn.net/jdluojing/article/details/7611254 六、用Cookie做处理 以User(假设有一个user类)举例说明,将用户id和"ok" + id分别放到cookie里面,根据需要设置cookie存活时间,然后放到response里面。在每次提交form表单时,先判断cookie中的name是否是已经提交过的表单名称,如果是就重定向到error页面。 示例代码如下: Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if (String.valueOf(user.getId()).equals(cookie.getValue())) { response.sendRedirect("error.jsp"); } else { Cookie cookie2 = new Cookie("ok" + user.getId(), String.valueOf(user.getId())); response.addCookie(cookie2); } }
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |