100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > form表单防止重复提交的N种方法

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

时间:2020-05-15 06:03:29

相关推荐

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

Form表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如:

(1)点击提交按钮两次。

(2)点击刷新按钮。

(3)使用浏览器后退按钮重复之前的操作,导致重复提交表单。

(4)使用浏览器历史记录重复提交表单。

(5)浏览器重复的HTTP请求。

(6)用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交。

参考网友建议和自己的体会,收集了以下几种有效防止表单重复提交的方法:

一、用Javascript禁掉提交按钮

表单提交之后,用JS置灰submit按钮,可防止心急用户重复点击提交按钮。

示例代码如下:

<script type="text/javascript">//设置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","");</script>

如果客户端禁用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`));

三、用Redirect-After-Post模式

1、用sendRedirect()函数转向

用户提交表单之后,执行重定向,转到成功信息页面。可避免用户按F5刷新页面和点击浏览器前进或后退导致的重复提交

示例代码如下:

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException,IOException{response.setContentType("text/html; charset=utf-8");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(令牌)

<%@ 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处理表单提交

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中的tokenSystem.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中的tokenString 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);}}

详情参考:/xdp-gacl/p/3859416.html

五、用Struts2的token机制

Struts2中的token标签可以用来生成一个唯一的标记,这个标记必须嵌套在form标签内使用,它将在form表单里插入一个隐藏字段并把标记保存到Session中。

示例代码如下:

1、在struts.xml里面需要进行如下配置:

<packagename="default"namespace="/"extends="struts-default"><action name="submit"class="action.SubmitAction"><result name="success">/success.jsp</result><result name="invalid.token">/input.jsp</result><interceptor-ref name="tokenSession"></interceptor-ref><interceptor-ref name="defaultStack"></interceptor-ref></action></package>

2、在需要提交的jsp页面加上<s:token></s:token>标签 (要使用token机制,必须使用struts2提供的标签库)

<form action="submit.action" method="post">name : <input type="text" name="name"/><br/>password : <input type="text" name=password/><br><s:token></s:token><input type="submit" value="submit"/></form>

详情参考:/jdluojing/article/details/7611254

六、用Cookie做处理以User(假设有一个user类)举例说明,将用户id和"ok" + id分别放到cookie里面,根据需要设置cookie存活时间,然后放到response里面。在每次提交form表单时,先判断cookie中的name是否是已经提交过的表单名称,如果是就重定向到error页面。如果客户端禁止了Cookie,该方法将不起任何作用

示例代码如下:

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);}}

作者:Paul Wen

来源:CSDN

原文:/Huozhiwu_11/article/details/78742886

版权声明:本文为博主原创文章,转载请附上博文链接!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。