如何解決重復下單的問題?(下單防重,重放攻擊)


如何解決重復下單的問題?(下單防重,重放攻擊)

問題來源:

近日發現某些用戶對一些商品進行多次下單,而且比較頻繁,而且下單時間都在同一秒內,懷疑產生重復請求

問題描述:

用戶在商品頁面,多次點擊下單按鈕,后台怎么知道是用戶對一個商品進行多次下單,還是人工誤操作或者客戶端異常進行重復請求下單了呢?

解決方案:

  1. 進入商品頁面,就是下單頁面的時候,產生一個不重復的隨機數。
  2. 下單的時候把這個隨機數帶上
  3. 下單校驗的時候,利用Redis緩存鎖,先鎖這個隨機數,再做業務處理,做完再釋放。

問題升級:

如果客戶端重復的下單請求過多,或者后台處理過快,就會產生所謂的重放攻擊。
如,客戶端請求模擬
請求A 20:18:01 xxx/order?storeid=1&randomNum=abcd123 用戶下單
請求A 獲得鎖成功,開始處理
請求B 20:18:01 xxx/order?storeid=1&randomNum=abcd123 用戶下單
請求B 獲得鎖失敗
請求C 20:18:01 xxx/order?storeid=1&randomNum=abcd123 用戶下單
請求C 獲得鎖失敗
請求A 下單成功,釋放鎖
請求D 20:18:01 xxx/order?storeid=1&randomNum=abcd123 用戶下單
請求D 獲得鎖成功,開始處理
請求D 下單成功,釋放鎖

針對同一個隨機數randomNum=abcd123居然下單成功2次,這就是重復攻擊帶來的危害

問題升級,解決方案:

  1. 下單校驗的時候,利用Redis緩存鎖,先鎖這個隨機數,鎖成功之后,判斷隨機數是否曾經處理過,如果沒有就把隨機數加入緩存設置時長為X,再做業務處理,做完再釋放
/**
     * 獲得鎖
     * @param lockId
     * @return
     */
    public boolean getLock(String lockId) {
        try {

            String KEY_LOCK_ID_="LOCK_ID_";
            String KEY_LOCK_HIS_ID_="LOCK_HIS_ID_";
            Boolean success = redisTemplate.opsForValue().setIfAbsent(KEY_LOCK_ID_+lockId, "lock");
            //解決重放攻擊
            if(success != null && success){
              if(hasKey(KEY_LOCK_HIS_ID_+lockId)){
                  success = false;
                  logger.error("【REDIS操作】【獲得鎖失敗】【已存在歷史鎖碼】【懷疑重放攻擊:"+lockId+"】");
              }else{
                  success = true;
                  set(KEY_LOCK_HIS_ID_+lockId,lockId,60*60*24);
              }
            }
            return success;
        } catch (Exception e) {
            logger.error("【REDIS操作】【獲得鎖錯誤】",e); 
            return false;
        }
    }

    /**
     * 釋放鎖
     * @param lockId
     */
    public void releaseLock(String lockId) {
        try {
            String KEY_LOCK_ID_="LOCK_ID_";
            redisTemplate.delete(KEY_LOCK_ID_ + lockId);
        } catch (Exception e) {
            logger.error("【REDIS操作】【釋放鎖錯誤】",e); 
        }
    }

  

問題描述:用戶下訂單購買,因為各種原因(網絡卡,快遞點擊等)重復提交2個或者以上一模一樣的訂單,由於是同時提交的,第一個訂單執行扣款生成訂單未完成時候,第二個已經進來了,導致付一筆錢購買了2次或多次商品 解決方案:

1、緩存lock,緩存此用戶的操作行為,注意緊緊緩存操作的標志,下次進入判斷此標志是否存在,存在即不進入數據庫事務

2、應用程序application lock,和1相比,會阻塞其他用戶的正常行為

3、模仿銀行扣款機制,數據表建一個隨機唯一標志,每次請求帶上這個標志,操作的同時進行修改這個標志

4、應用程序生成唯一標志,數據庫做字段的唯一索引

5、扣款為負數的事務進行回滾

6、使用事務的隔離級別

7、使用redis的incr控制用戶的並發數,memcache的add也可以實現這種效果,memcached借助cas


免責聲明!

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



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