formHash的實現


 

 

問題重現

在我們的項目中,有一個商店購買的頁面,流程是這樣的:  選擇道具  ----->  點擊購買   -------> 獲得道具 ------> 扣除銀幣

如果玩家在一秒鍾並發的請求這個URL,  如果他有100個銀幣,只可以買10個道具,由於並發的問題,他還可以買100個道具,到時候,他的銀幣的數量可能扣除為負數。這樣,對游戲來說,是非常嚴重的問題。

並發的原理是這樣的: 當玩家第一次購買道具的的時候,讀取玩家的余額,如果大於道具的價格,系統把道具給玩家,然后在扣除玩家的余額。在我我把道具給了玩家過程中,由於大量的請求過來,還沒有來得及把玩家的錢扣除,所以,導致了玩家買到了更多的東西

問題所在

如果扣“除銀幣”在“獲得道具”之前完成,就基本上可以避免了這種問題,但是,由於我們道具的特殊設定,不能先扣除銀幣,所以不能這樣做

這樣,就只能避免玩家重復的提交同一個買道具的URL,產生了大量的並發。方法是,URL上面加一個formHash,每次都生成一個新的formHash.那么就防止了頁面多次提交了。

 

formHash的生成代碼

formHash保存在memcache中

    // 生成新的 formHash
    public function refreshFormHash($formName)
    {
        // 生成隨機碼
        $formHash = md5('VoyageMobile:' . date('md') . ':' . mt_rand() . ':' . $formName);

        $cacheObj = Com_Cache::getInstance('Memcache');
        $cacheKey = 'formHash:' . $formName;

        // 將 formHash 寫入到 Memcache 中
        $cacheObj->set($cacheKey, $formHash);

        // 傳出到模板中
        $this->assign('formHash', $formHash);

        return $formHash;
    }

  

formHash的驗證

    /**
     * 驗證 formHash 是否正確
     *
     * @param string $formName
     * @param mixed $formHashGet
     * @param bool $clear 是否取完即清除
     * @return bool
     */
    public function validFormHash($formName, $formHashGet = null, $clear = true)
    {
      // 頁面中傳過來的formHash if ($formHashGet === null) { $formHashGet = $this->getx('formHash'); } $cacheObj = Com_Cache::getInstance('Memcache'); $cacheKey = 'formHash:' . $formName; $formHash = $cacheObj->get($cacheKey); // 取完即清除(formHash只能用一次) $clear && $cacheObj->delete($cacheKey); return $formHash == $formHashGet ? true : false; }

  

formHash的使用

在道具購買的首頁中,系統生成一個formHash.

public function shopIndex()
{
  // 生成道具的列表 

  // 生成formHash 
  $this->refreshFormHash();  
    
}

  

formHash的驗證

在購買道具的函數中,必須驗證formHash,而且,必須生成新的formHash,並分配到頁面中

    /**
     * 購買提交
     */
    public function purchaseAction()
    {
        // 驗證請求合法性
        if (! $this->validFormHash('bmItem')) {
            $this->vRedirect('/main/?err=Invalid_Request_FormHash');
        }

        // 重新刷新 formHash
       $this->refreshFormHash('bmItem');

        //  購買流程
}

  

 

   注意問題

   某些頁面是ajax請求,不刷新頁面,這時候把新生成的formHash 動態的在頁面中生成。

 


免責聲明!

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



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