zoukankan      html  css  js  c++  java
  • 防止表单重复提交

    一、场景
    1、由于用户误操作,多次点击表单提交按钮。
    2、由于网速等原因造成页面卡顿,用户重复刷新提交页面。
    3、黑客或恶意用户使用postman等工具重复恶意提交表单(攻击网站)。
     
    二、解决方案
    1、通过JavaScript屏蔽提交按钮(不推荐)
    通过js代码,当用户点击提交按钮后,屏蔽提交按钮使用户无法点击提交按钮或点击无效,从而实现防止表单重复提交。
    缺点:js代码很容易被绕过。比如用户通过刷新页面方式,或使用postman等工具绕过前段页面仍能重复提交表单。因此不推荐此方法。
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
            <!DOCTYPE HTML>
            <html>
            <head>
             <title>表单</title>
                <script type="text/javascript">
                //默认提交状态为false
                var commitStatus = false;
                function dosubmit(){
                      if(commitStatus==false){
                    //提交表单后,讲提交状态改为true
                      commitStatus = true;
                      return true;
                     }else{
                      return false;
                  }
                 }
          </script>
         </head>
       
            <body>
                <form action="/path/post" onsubmit="return dosubmit()" method="post">
                 用户名:<input type="text" name="username">
                <input type="submit" value="提交" id="submit">
                </form>
            </body>
        </html>
    View Code
    2、给数据库增加唯一键约束(简单粗暴)
    在数据库建表的时候在ID字段添加主键约束,用户名、邮箱、电话等字段加唯一性约束。确保数据库只可以添加一条数据。
    -- 数据库加唯一性约束sql:
    alter table tableName_xxx add unique key uniq_xxx(field1, field2)
    缺点:通过数据库加唯一键约束能有效避免数据库重复插入相同数据。但无法阻止恶意用户重复提交表单(攻击网站),服务器大量执行sql插入语句,增加服务器和数据库负荷。
     
    3、利用Session防止表单重复提交(推荐)
    1】实现原理:
    服务器返回表单页面时,会先生成一个token保存于session,并把该token传给表单页面。当表单提交时会带上token,服务器拦截器Interceptor会拦截该请求,拦截器判断session保存的token和表单提交token是否一致。若不一致或session的token为空或表单未携带token则不通过。
     
    首次提交表单时session的token与表单携带的token一致走正常流程,然后拦截器内会删除session保存的token。当再次提交表单时由于session的token为空则不通过。从而实现了防止表单重复提交。
    2】Struts2实现
    // 1、要防止重复提交的jsp页面:
    <s:token /><!-- 生成令牌号,防止表单重复提交 -->
    // 2、struts.xml
    <package name="default" namespace="/" extends="struts-default">
            <action name="regist" class="cn.itcast.action.RegistAction">
                <result name="invalid.token">/token.jsp</result><!-- name必须是: invalid.token -->
                <interceptor-ref name="token" />
                <interceptor-ref name="defaultStack" />
            </action>
        </package>
    // 3、token.jsp
     您已经重复提交表单,请刷新后重试! <br>

    3】session实现

    // jsp页面
    <% //生成一个令牌
          String token=UUID.randomUUID().toString();
          session.setAttribute("token", token);
    %>
    <form action="${pageContext.request.contextPath}/regist" method="get">
              <input type="hidden" name="token" value="<%=token%>">
              username:<input type="text" name="username"><br>
              password:<input type="password" name="password"><br>
              <input type="submit" value="注册">
          </form>
        
    // RegistServlet.java
    public class RegistServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            String username = request.getParameter("username");
            String password = request.getParameter("password");
    
            String token = request.getParameter("token");
            String _token = (String) request.getSession().getAttribute("token");
            request.getSession().removeAttribute("token");
            if (token.equals(_token)) {
                System.out.println("将" + username + " 与" + password
                        + "存储到数据库中,完成注册");
            } else {
                response.getWriter().write("不允许表单重复提交");
            }
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }
    4、使用AOP自定义切入实现
  • 相关阅读:
    Shader 结构体中语义的理解
    计算包围盒中心坐标
    c#脚本控制shader
    PS2键盘 + LCD12864 实验
    基于M9K块配置ROM的LCD12864图片显示实验
    LCD12864 液晶显示-汉字及自定义显示(串口)
    LCD12864 液晶显示-汉字及自定义显示(并口)
    基于Verilog HDL 的数字电压表设计
    基于Verilog HDL的ADC0809CCN数据采样
    触发器(基本的SR触发器、同步触发器、D触发器)
  • 原文地址:https://www.cnblogs.com/shelly0307/p/10916024.html
Copyright © 2011-2022 走看看