账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    如何防止jsp页面form表单重复提交,注意不是幂等性
    41
    0

    问题描述

    如何防止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
        }
    
    }
    ### 你期待的结果是什么?实际看到的错误信息又是什么?
    对于场景三,到底如何解决?
    1
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 10 元积分
        全部回答
    • 0
    更多回答
    网站公告
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部