• 如何处理 api 重复提交,接口幂等性


       表单重复提交请求:

    由于重复点击或者网络重发 
    1)点击提交按钮两次;
    2)点击刷新按钮;
    3)使用浏览器后退按钮重复之前的操作,导致重复提交表单;
    4)使用浏览器历史记录重复提交表单;
    5)浏览器重复的HTTP请;
    6)nginx重发等情况;
    7)分布式RPC的try重发等;
    
    作者:锦成同学
    链接:https://juejin.im/post/5d31928c51882564c966a71c
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

      创建一个 Dynamic Web Project 演示

       FormServlet

    View Code

      index.jsp

    View Code

      访问 http://localhost:8080/form-repeat-demo/,因为请求的延迟,快速点击按钮,会导致重复提交。

    1、前端表单提交后通过 js 禁止按钮点击

    <form action="${pageContext.request.contextPath}/FormServlet" method="post">
        <input type="text" name="name" /><br/>
        <input type="button" value="提交" onclick="handleSubmit(this)" />
    </form>
    <script type="text/javascript">
        function handleSubmit(buttonObj) {
            document.forms[0].submit();
            buttonObj.disabled = true;
        }
    </script>

      点击按钮后,按钮变暗,不能继续点击;浏览器跳转到 http://localhost:8080/form-repeat-demo/FormServlet

       但是 F5 刷新或者后退,仍然可以重复提交表单。所以,这种方法并不能完全解决。

    2、token 令牌机制(表单令牌与服务器保存的令牌比对)

      token 令牌机制:表单提交时发送一个 token,这个 token 之前已经保存在 服务器,当处理一次请求后删除 服务器中 token,保证只处理一次表单提交请求。

      这里演示服务器令牌保存在 session。

      修改 index.jsp:

    View Code

      FormServlet 中判断表单提交 的 token 和 session 中的 token

    View Code

      这样,点击提交按钮后,发送请求,浏览器地址变为提交表单的地址 http://localhost:8080/form-repeat-demo/FormServlet。F5 刷新页面和回退页面继续点击提交按钮,都会提示重复提交信息。

      这样,表单就只能提交一次。如果想要继续提交,需要刷新页面,重写生成页面更新 token。

      上面的演示,显然需要使用到动态页面技术(获取到的页面是动态页面,需要往 session 中添加 token)。

      前后端分离架构中,前端都是静态页面,数据提交时要向服务申请 token(或前后端使用同一规则),token 放到redis 或 内存。提交后同时删除 token。

      token 生成可以参考 本文最后链接 1 和 3。

    3、nonce 机制 + 表单校验

      nonce 机制:每一次请求过来 nonce 加一;后端保存前一次请求的 nonce,校验每次请求的 nonce。如果nonce 不大于保存的 nonce,则认为是重复请求。这其实也是防重放攻击的一种处理。HTTP 中摘要(Digest )认证就是采用这种机制。

      另外为了保证每次请求都是用户希望的请求,表单输入可以做非空校验等,点击提交按钮后清空输入。这样用户重复点击,也通不过校验。

    4、借助数据库

      insert 使用唯一索引, update使用乐观锁 version版本法 这种在大数据量和高并发下效率依赖数据库硬件能力,可针对非核心业务

    参考:

      1)API接口幂等设计(Token方式防止表单重复提交或网络延迟)

      2) 8种方案解决重复提交问题

      3)spring boot 通过AOP防止API重复请求

      4)如何防止接口重复请求

      5)SpringBoot利用AOP防止请求重复提交

      6) https://www.jianshu.com/p/364a6f466a2a

      7) https://cloud.tencent.com/developer/article/1460588
    ---

  • 相关阅读:
    mybatis多参数传递(包括数组)
    mysql查询树状目录所有子节点
    Kettle ETL调用 java代码来进行数据库的增删改查
    java dom4j解析器使用
    Linux查看系统位数
    Linux查看系统是32位还是64位命令(getconf WORD_BIT和getconf LONG_BIT)
    Centos7下Redis缓存清理_FZlion
    springboot+vue项目实战(代码可运行)
    SpringBoot控制台打印SQL语句
    Error running ‘Application‘: Command line is too long
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12748070.html
Copyright © 2020-2023  润新知