【重复提交表单】表单重复提交的三种情况,解决办法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sinat_42483341/article/details/100122270

引入

看一个重复提交表单的例子
在这里插入图片描述

F12可以看到,请求体中的参数在刷新页面之后仍然保留,因此每一次刷新页面,都会把现有的请求体中的表单数据提交一次到服务器,而接收的页面还是insert.jsp,于是造成了重复提交表单,又新增了一条相同的数据。
在这里插入图片描述
解决方式:在servlet中,使用重定向(两次请求),而非请求转发(一次请求),可以防止表单重复提交。
在这里插入图片描述
下面,我们来看重复提交表单的三种情况、解决方式。


第一种情况

第一种情况:提交完表单以后,不做其他操作,直接刷新页面,表单会提交多次。

在servlet中写一句输出,用来判断是否提交多次

System.out.println("已经插入");
request.getRequestDispatcher("/login_success.jsp").forward(request, response);

这样的话,刷新多少次,就会在控制器显示多少个“已经插入”。
在这里插入图片描述
根本原因:Servlet处理完请求以后,直接转发到目标页面,这样整个业务只发送了一次请求,那么当你在浏览器中点击刷新会一直都会刷新之前的请求。

解决方法:不用转发到另一页面,采用重定向的方式跳转到目标页面

response.sendRedirect("/day0815-session/login_success.jsp");

第二种情况

第二种情况:在提交表单时,如果网速较差,可能会导致点击提交按钮多次,这种情况也会导致表单重复提交。

解决方法:点击提交按钮之后,使按钮不可用。通过js完成

<script type="text/javascript">
    window.onload = function(){ 
        //获取按钮的对象
        var btn = document.getElementById("btn");
        //为按钮绑定单击响应函数
        btn.onclick = function(){     
            //点击以后使按钮不可用
            this.disabled=true;  
            //当将提交按钮设置为不可用时,会自动取消它的默认行为
            //手动提交表单
            this.parentNode.submit();  
        };
    };
</script>
<br>
<br><form action="${pageContext.request.contextPath }/SessionServlet" >
	<br>user:<input type="text" name="username">
	<br>password<input type="password" name="pwd">
	<br><input type="submit" value="提交" id="btn">
<br></form>

注意“提交”按钮,此时已经不可按!
在这里插入图片描述


第三种情况

第三种情况:表单提交成功以后,直接点击浏览器上回退按钮,不刷新页面,然后点击提交按钮再次提交表单。

-根本原因:因为服务器在处理请求时,不会检查是否为重复提交的请求。

解决方案:
使用一个token的机制
- token就是令牌的意思
- 服务器在处理请求之前先来检查浏览器的token
- token由服务器来创建,并交给浏览器,浏览器在向服务器发送请求时需要带着这个token
- 服务器处理请求前检查token是否正确,如果正确,则正常处理,否则返回一个错误页面
- 服务器所创建的token只能使用一次
- token一般使用一个唯一的标识

在jsp页面,获取uuid作为token

-UUID:32位字符串,通常作为对象或者表的唯一标识,根据机器码和时间戳(从1970年1月1日开始到现在)生成。
  
jsp

<%
    String uuid = UUID.randomUUID().toString();
    session.setAttribute("uuid", uuid);
%>
<br>${errormsg }<br><form action="${pageContext.request.contextPath }/SessionServlet" ><br>  
<input type="text" name="uuid" value="<%=uuid %>"/><br>  
user:<input type="text" name="username"><br>  
password<input type="password" name="pwd"><br>  
<input type="submit" value="提交" "><br></form>

servlet

String reqUUID = request.getParameter("uuid");
HttpSession session = request.getSession();
String sessUUID = (String) session.getAttribute("uuid");
session.removeAttribute("uuid");
     
if(reqUUID.equals(sessUUID)){
    response.sendRedirect(request.getContextPath()+"/login_success.jsp");
    System.out.println("已经插入");
}else{
    request.setAttribute("errormsg", "重复登陆");
    request.getRequestDispatcher("/3.jsp").forward(request, response);
}

表单重复提交的危害:
- 向数据库中插入大量的重复且没有意义的数据,占用服务器的资源
- 处理请求服务器并没有检查请求是否为重复的请求,导致恶意的攻击

猜你喜欢

转载自blog.csdn.net/sinat_42483341/article/details/100122270