防止form表单重复提交的X种方法

您所在的位置:网站首页 web表单提交的方法 防止form表单重复提交的X种方法

防止form表单重复提交的X种方法

2024-07-11 03:03| 来源: 网络整理| 查看: 265

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.jsp

2、在需要提交的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