如何防止jsp页面form表单重复提交,注意不是幂等性

新手上路,请多包涵

问题描述

如何防止jsp页面form表单重复提交,注意不是幂等性

问题出现的环境背景及自己尝试过哪些方法

我尝试按照https://m.jb51.net/article/121255.htm里面给出的解决方式去解决。发现第三种情况:表单提交成功以后,直接点击浏览器上回退按钮,不刷新页面,然后点击提交按钮再次提交表单。这里给出的解决方案并不能解决这种情况。
按照情况,可分为三种重复提交的场景:
场景一:在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交
场景二:表单提交后用户点击【刷新】按钮导致表单重复提交
场景三:用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交

对于【场景二】和【场景三】导致表单重复提交的问题,既然客户端无法解决,那么就在服务器端解决,在服务器端解决就需要用到session了。

  具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
  在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

  1. 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。这种情况我不明白,为什么会出现不同的情况,不应该一直相同吗?
  2. 当前用户的Session中不存在Token(令牌)
  3. 用户提交的表单数据中没有Token(令牌)

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
    Date d = new Date();
    long dl = d.getTime();
    session.setAttribute("uuid", dl);
 %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>1323132</title>
  </head>
  
  <body>
    <form action="test" method="get">
        <input type="text" name="uuid" value="<%=dl %>"/><br>
        user:<input type="text" name="username"><br>
        password:<input type="password" name="pwd"><br>  
        <input type="submit" value="提交"><br>
    </form>
  </body>
</html>~~~~
package single;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class test extends HttpServlet {

    public test() {
        super();
    }

    public void destroy() {
        super.destroy(); 
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String reqUUID = request.getParameter("uuid");
        HttpSession session = request.getSession();
        String sessUUID = (long) session.getAttribute("uuid")+"";
        session.removeAttribute("uuid");
          
        if(reqUUID.equals(sessUUID)){
            System.out.println("正常");
        }else{
            System.out.println("重复提交");
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    public void init() throws ServletException {
        // Put your code here
    }

}
### 你期待的结果是什么?实际看到的错误信息又是什么?
对于场景三,到底如何解决?
阅读 2.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题