重復提交的幾種情況
1、利用JavaScript防止表單重復提交
按鈕禁用
2、利用Session令牌防止表單重復提交
具體的做法:在服務器端生成一個唯一的隨機標識號,專業術語稱為Token(令牌),同時在當前用戶的Session域中保存這個Token。然后將Token發送到客戶端的Form表單中,在Form表單中使用隱藏域來存儲這個Token,表單提交的時候連同這個Token一起提交到服務器端,然后在服務器端判斷客戶端提交上來的Token與服務器端生成的Token是否一致,如果不一致,那就是重復提交了,此時服務器端就可以不處理重復提交的表單。如果相同則處理表單提交,處理完后清除當前用戶的Session域中存儲的標識號。
在下列情況下,服務器程序將拒絕處理用戶提交的表單請求:
存儲Session域中的Token(令牌)與表單提交的Token(令牌)不同。
當前用戶的Session中不存在Token(令牌)。
用戶提交的表單數據中沒有Token(令牌)。
后端代碼
public class FormServlet extends HttpServlet { private static final long serialVersionUID = -884689940866074733L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String token = TokenProccessor.getInstance().makeToken();//創建令牌 System.out.println("在FormServlet中生成的token:"+token); request.getSession().setAttribute("token", token); //在服務器使用session保存token(令牌) request.getRequestDispatcher("/form.jsp").forward(request, response);//跳轉到form.jsp頁面 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3、對外接口(服務端調用服務端)如何防止重復提交
可以設置字段狀態,在某種狀態插入,某種狀態下更新,某種狀態下不插入,達到冪等性
4、后端服務器如何簡單的避免重復提交
業務場景:用戶點擊購買后,修改訂單狀態,修改用戶賬戶余額,並添加用戶消費記錄。
分析:這里在同一個事務里有三個動作,兩個是更新,一個是添加。如果這時候在更新完出現並發情況,那么用戶消費記錄可能會多出一條,用戶賬戶余額也可能出現錯誤。那么該如何防止呢?在修改前查詢訂單狀態判斷是否已經修改過明顯不能解決問題,因為並發可能發生在查詢之后。
解決思路:數據庫一般默認update操作會占有一個行級鎖,當第一次請求的事務還未結束時,第二次重復請求是無法修改這條記錄的。我們讓修改操作都加上一個修改前的條件判斷,這樣第二次請求再來修改的時候會發現修改不成功,這時回滾事務即可避免並發。
解決辦法:在修改訂單時增加一個判斷(判斷其應該是未支付的訂單),然后返回更新的記錄條數,如果為0則拋出異常,回滾當前事務。
sql語句如下:
update order set status = 1 where oid = 1 and status = 0;
在mybatis中可以獲取記錄更新的條數
int update(Map map);
5、在數據庫添加約束
在數據庫里添加唯一約束或者創建唯一索引,防止出現重復數據。是最有效的防治重復提交的方法了。
出現異常,回滾
6、使用Post/Redirect/Get
Post/Redirect/Get簡稱PRG,是一種可以防止表單數據重復提交的一種Web設計模式,像用戶刷新提交響應頁面等比較典型的重復提交表單數據的問題可以使用PRG模式來避免。例如:當用戶提交成功之后,執行客戶端重定向,跳轉到提交成功頁面。
注意:PRG設計模式並不適用所有的重復提交情況,比如:
1)由於服務器響應緩慢,用戶刷新提交POST請求造成的重復提交。
2)用戶點擊后退按鈕,返回到數據提交界面,導致的數據重復提交。
3)用戶多次點擊提交按鈕,導致的數據重復提交。
4)用戶惡意避開客戶端預防多次提交手段,進行重復數據提交
原文:https://blog.csdn.net/douxingpeng1/article/details/81708205