如何處理 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
---


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM