• session的token令牌机制防止表单重复提交


    本例通过前端js+后端session的token机制完美解决表单重复提交问题:

    表单重复提交产生的原因:

    1.网络延迟,连续点击。(js控制连续点击导致重复提交问题)

    2.提交成功后,刷新页面。(session的token控制)

    3.提交成功后,后退,再次点击提交。(session的token控制)

    提交页面:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title>Form表单</title>
        <script type="text/javascript">
            var isSubmitFlag = false;
            function isSubmit() {
                if(!isSubmitFlag){
                    isSubmitFlag = true;
                    return isSubmitFlag;
                }else{
                    return false;
                }
            }
        </script>
    </head>
    
    <body>
    <%--token能防止表单刷新,后退提交导致的重复提交,防止不了连续点击导致的重复提交。连续点击的估计得在前端js处理。--%>
    <form action="${pageContext.request.contextPath}/submitForm" method="post" onsubmit="return isSubmit()">
        <input type="hidden" name="token" value="${token}">
        用户名:<input type="text" name="userName">
        <input type="submit" value="提交" id="submit">
    </form>
    </body>
    </html>

    token生成通过页面跳转控制器:

    package com.cookie_session.formRepeat.token;
    
    import com.cookie_session.customeSessionAndToken.TokenUtils;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    /**
     * Created by Administrator on 2021/6/28.
     */
    @WebServlet("/toForm")
    public class ToFormServlet extends HttpServlet{
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            HttpSession session = req.getSession();
            session.setAttribute("token",TokenUtils.getSessionId());
            req.getRequestDispatcher("form_token.jsp").forward(req,resp);
        }
    }

    提交表单后处理控制器:

    package com.cookie_session.formRepeat;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * Created by Administrator on 2021/6/28.
     */
    @WebServlet("/submitForm")
    public class TokenFormServlet extends HttpServlet{
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String userName = (String) req.getParameter("userName");
            resp.setContentType("text/html;charset=utf-8");
            boolean isSubmitFlag = isSubmit(req);
            if(!isSubmitFlag){
                resp.getWriter().write("您已经提交过数据或者token错误!");
                return;
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("userName:" + userName);
            req.getSession().removeAttribute("token");
        }
    
        /*
            这个能防止表单刷新,后退返回导致的重复提交,防止不了连续点击导致的重复提交。
            连续点击的估计得在前端js处理。
         */
        private boolean isSubmit(HttpServletRequest req) {
            String paramToken = req.getParameter("token");
            String sessionToken = (String) req.getSession().getAttribute("token");
            if(sessionToken == null){
                return false;
            }
            if(!sessionToken.equals(paramToken)){
                return false;
            }
            return true;
        }
    }

    注意:

    1.由于token机制在servlet或者controller中无法控制连续点击导致重复提交的问题。因为连续点击的时候,可能同时判断了isSubmit()方法,

    这时候还没有提交完成,session中的token还没清空。所以需要前端js控制连续点击问题。

    2.而提交成功后的刷新页面和后退再次提交,

    都是servlet或者controller已经执行完成,此时session中的token已经清空。刷新或者后退的再次提交,sessionToken为空判断方法不为真。

    直接返回"您已经提交过数据或者token错误!"

    至此js+token完美解决表单重复提交问题。(此方法实用于单机系统,也就是单个服务器)。

    集群,负载均衡轮询的话,多次请求可能访问到不同机器,不同机器jvm不同,session不同,这时候需要解决session共享问题。可使用redis解决。

    token放在redis中,表单再次提交,从redis拿到token进行比较判断,确认是否重复提交。

  • 相关阅读:
    ios系统滚动穿透
    移动h5 开发遇到ios系统的各种问题汇总
    移动端选择时间时软键盘弹出问题
    ios系统设置-webkit-overflow-scrolling: touch导致z-index 失效 (弹窗层级设置无效)- 替代方案
    npm i 报错 npmERR! code Z_BUF_ERROR errno -5 // 后继 chromedriver.zip 相关问题报错解决
    mysql、orcale、sql server的区别
    jsp中的select选择
    sql面试
    java面试题
    struts2总结
  • 原文地址:https://www.cnblogs.com/super-chao/p/14949504.html
Copyright © 2020-2023  润新知