自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

webgame中常見安全問題、防御方式與挽救措施

安全 應(yīng)用安全
在本文中,筆者以webgame研發(fā)者角度,切合游戲業(yè)務(wù)模塊邏輯,從業(yè)務(wù)需求,數(shù)據(jù)庫設(shè)計(jì),程序編寫,操作方式上來講解漏洞形成原理,規(guī)避方案。

在本文中,筆者將以webgame研發(fā)者角度,切合游戲業(yè)務(wù)模塊邏輯,從業(yè)務(wù)需求,數(shù)據(jù)庫設(shè)計(jì),程序編寫,操作方式上來講解漏洞形成原理,規(guī)避方案,也歡迎大家討論。

登錄認(rèn)證

近幾年,網(wǎng)頁游戲幾乎都是以聯(lián)運(yùn)方式運(yùn)營,意味著游戲服務(wù)器本身不保存用戶密碼,用戶登錄在平臺(tái),通過平臺(tái)跟游戲服務(wù)器的接口對(duì)接登錄。接口做加密認(rèn)證。故webgame的帳號(hào)密碼安全問題,這里不提了。但登錄認(rèn)證的hash字符串安全,也還是要注意的。比如登錄hash字符串的生效時(shí)間,hash字符串的加密參數(shù)來源,比如包括用戶名、登錄IP,瀏覽器user-agent等數(shù)據(jù),以防止改hash被泄漏了,也是很難通過服務(wù)器的驗(yàn)證。

游戲充值

webgame的游戲充值流程,跟普通網(wǎng)頁充值流程一致,沒有特殊的地方,其不同點(diǎn)就是跟其他眾多平臺(tái)做聯(lián)合運(yùn)營時(shí),勢(shì)必要每個(gè)公司做接口對(duì)接,且接口規(guī)范各式各樣,且游戲廠商沒有話語權(quán),必須按照他們的接口規(guī)范來,這實(shí)在棘手。騰訊的充值接口的驗(yàn)證方式,安全性做的較為突出,大約代碼:

// 返回參數(shù)列表
$signKey = array('openid','appid','ts','payitem','token','billno','version','zoneid','providetype','amt','payamt_coins','pubacct_payamt_coins');
$sign = array();
//從GET參數(shù)中,對(duì)比找出上面參數(shù)的值
foreach($signKey as $key ) {
if (isset($data[$key]))
{
$sign[$key] = $data[$key]; //只有 GET里有的參數(shù),才參與sig的計(jì)算
}
}
######開始生成簽名############
//1: URL編碼 URI
$url = rawurlencode($url);
//2:按照key進(jìn)行字典升序排列
ksort($sign);
//3: &拼接,并URL編碼
$arrQuery = array();
foreach ($sign as $key => $val )
{
$arrQuery[] = $key . '=' . str_replace('-','%2D',$val);
}
$query_string = join('&', $arrQuery);
//4 以POST方式拼接 1、3 以及URL
$src = 'GET&'.$url.'&'.rawurlencode($query_string);
// ## 構(gòu)造密鑰
$key = $this->config->get('qq_appkey').'&';
//### 生成簽名
$sig = base64_encode(hash_hmac("sha1", $src, strtr($key, '-_', '+/'), true));
if ( $sig != $data['sig'] ) {
$return['ret'] = 4;
$return['msg'] = '請(qǐng)求參數(shù)錯(cuò)誤:(sig)';
$this->output->set(json_encode($return));
return ;
}

在此基礎(chǔ)上,還可以做的嚴(yán)謹(jǐn)點(diǎn):

增加隨機(jī)參數(shù)名、參數(shù)值。隨機(jī)參數(shù)名、參數(shù)值由聯(lián)運(yùn)方隨機(jī)生成,按照參數(shù)名的字符串所屬ASCII碼順序排序,參數(shù)名、參數(shù)值均參與sign的計(jì)算,增加暴力破解密鑰(app key)難度。

增加回調(diào)驗(yàn)證訂單號(hào),金額信息。游戲充值服務(wù)器接收到充值請(qǐng)求時(shí),反向到該平臺(tái)回調(diào)接口,確認(rèn)此筆訂單有效性,以防止加密密鑰泄漏的問題。

遠(yuǎn)程文件引入

在網(wǎng)頁游戲的研發(fā)中,多數(shù)都是使用框架來做,即使用REQUEST來的參數(shù),作為請(qǐng)求文件名的一部分,來使用,那么很容易形成遠(yuǎn)程文件引入的漏洞。在我們之前的游戲中,曾出現(xiàn)過一例這樣的漏洞問題。

// Load the local application controller
// Note: The Router class automatically validates the controller path. If this include fails it
// means that the default controller in the Routes.php file is not resolving to something valid.
if ( ! file_exists(APPROOT.'controllers/'.load('Router')->getDirectory().load('Router')->getClass().EXT))
{
load('Errors')->show404('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');
}
include(APPROOT.'controllers/'.load('Router')->getDirectory().load('Router')->getClass().EXT);
load('Benchmark')->mark('load_basic_class_time_end');

 

 

webgame中的遠(yuǎn)程文件引入

從代碼以及案例圖中,可以看到對(duì)于REQUEST的參數(shù)沒有過濾處理,直接作為文件名來include引入的,故導(dǎo)致這種問題,類似上頁圖中QQ群網(wǎng)站的漏洞。若PHP version < 5.3.4 ,還會(huì)發(fā)生Null(%00) 截?cái)嗟膯栴},帶來更大的安全問題。在我們新的項(xiàng)目中,我們更改了實(shí)現(xiàn)方式,我們游戲所有接口都會(huì)走gateway,gateway里,對(duì)控制器名做類名規(guī)范的檢測(cè)處理,再在指定幾個(gè)目錄下做autoload加載文件,且還會(huì)對(duì)REQUEST的類名、方法用ReflectionClass反射類的處理,檢測(cè)到類、方法、參數(shù)是否合法。一來避免『遠(yuǎn)程文件引入』漏洞問題,二來便于前后端聯(lián)調(diào)時(shí),拋出更詳細(xì)的異常,方便調(diào)試。下面為參考代碼:

require_once CONFIG_PATH . "/auto.php";
spl_autoload_register("__autoload");
……
//默認(rèn)消息格式
$view->clear();
$view->error(MLanguages::COM__INVALID_REQUST);
$msg = new Afx_Amf_plugins_AcknowledgeMessage($val->data[0]->$messageIdField);
$msg->setBody($view->get());
$message->data = $msg;
…
$a = new Yaf_Request_Simple();
$a->setControllerName($method[0]);
$a->setActionName($method[1]);
$objC = new ReflectionClass($method[0]."Controller");
$arrParamenter = $objC->getMethod($method[1]."Action")->getParameters();
$arrRequest = isset($val->data[0]->body[0]) ? (array)$val->data[0]->body[0] : array();
$bCanCall = true;
foreach ($arrParamenter as $objParam)
{
$parm = $objParam->getName();
$bIsOption = $objParam->isOptional(); //是否為可選參數(shù)
if (isset($arrRequest[$parm]))
{
$a->setParam($parm , $arrRequest[$parm]);
}
elseif ($objParam->isOptional())
{
//可選參數(shù)
}
else
{
$bCanCall = false;
}
}
if ($bCanCall)
{
$rp = $app->getDispatcher()->dispatch($a);
$msg = new Afx_Amf_plugins_AcknowledgeMessage($val->data[0]->$messageIdField);
$msg->setBody($view->get());
$message->data = $msg;
}

SQL 注入

SQL注入原理、方式,跟普通web應(yīng)用一樣,沒什么特別的,在使用REQUEST來的參數(shù)時(shí),過濾處理即可。可能在消息格式,以及注入操作簡便上,會(huì)蒙蔽研發(fā)人員的眼睛,被忽略掉了。比如我們項(xiàng)目的AMF消息格式,在前端界面沒出來之前,我們后端程序員一般使用Pinta來模擬操作,調(diào)試程序。前端界面出來之后,會(huì)使用Charles proxy來捕捉http請(qǐng)求。在這些過程中,請(qǐng)求接口、參數(shù)的構(gòu)造,沒有普通web那么簡單。研發(fā)人員也容易忽略對(duì)請(qǐng)求參數(shù)的過濾,故很容易形成這種問題。形成原理見:《WEB開發(fā)安全與運(yùn)維安全淺見》,防御方式做過濾處理,或SQL預(yù)編譯。

 

 

AMF消息格式的WEBGAME中的SQL注入

 

 

AMF消息格式的WEBGAME中的SQL注入

為了提高游戲服務(wù)器的吞吐能力,網(wǎng)頁游戲的架構(gòu)也是一直在演變的。在之前以Mysql作為數(shù)據(jù)存儲(chǔ)的webgame架構(gòu)中,其他節(jié)點(diǎn)都是可以水平擴(kuò)展,或者說依賴簡單粗暴的增加服務(wù)器來解決,單單作為唯一數(shù)據(jù)存儲(chǔ)中心,不能這么做。為此,很多webgame的數(shù)據(jù)存儲(chǔ)改用Nosql來代替,甚至java、C/C++的游戲數(shù)據(jù),直接在內(nèi)存中操作,游戲關(guān)服時(shí),才寫入到DB中。故SQL注入的問題,也會(huì)越來越少。

通訊協(xié)議與消息格式

網(wǎng)頁游戲雖然名字叫網(wǎng)頁游戲,但通訊協(xié)議并非全是http,也有很多使用socket,以及http+socket并用的做法。我們是http協(xié)議+amf消息格式,以及socket并用來實(shí)現(xiàn)。在http與https的取舍上,我們考慮到ssl的啟用后,大量的ssl解密加密運(yùn)算,勢(shì)必會(huì)增加服務(wù)器大量的CPU計(jì)算壓力。而傳輸?shù)膬?nèi)容,多數(shù)是游戲業(yè)務(wù)的操作,響應(yīng),是能接受被監(jiān)聽嗅探的行為的(認(rèn)證信息除外)。站在安全角度,這不能理解。但站在產(chǎn)品角度,考慮一下 投入產(chǎn)出,然后選擇http通訊,也是可以理解的。socket在我們游戲中,除了在聊天應(yīng)用上使用外,在一些組隊(duì)、幫派戰(zhàn)之類需要多個(gè)玩家之間同步數(shù)據(jù)信息時(shí),我們也會(huì)使用socket來推送數(shù)據(jù)。在使用socket作為所有業(yè)務(wù)傳輸?shù)膮f(xié)議時(shí),協(xié)議格式一般都是開源協(xié)議,比如msgpack、protobuf之類,或者自定義的協(xié)議。使用自定義協(xié)議時(shí),務(wù)必檢測(cè)整個(gè)消息包的每一個(gè)參數(shù),類型范圍,避免個(gè)別超大數(shù)值、邊界數(shù)值出現(xiàn),導(dǎo)致主程序內(nèi)存越界,以至于服務(wù)宕機(jī),無法正常服務(wù)的情況發(fā)生。

金幣復(fù)制-整型溢出

上周周六開周會(huì)時(shí),聽到其他項(xiàng)目組的一個(gè)關(guān)于整型溢出導(dǎo)致產(chǎn)生刷金幣的問題。在這里,我抽象該案例,分享一下。商城出售開啟背包格子的所需道具『梧桐木』。在游戲中,用戶包裹格子數(shù)量一般都會(huì)作為一個(gè)收費(fèi)點(diǎn),一款游戲的格子大約為每行7格子,一共8行這樣。比如前面3行是默認(rèn)開放的,第4行是收費(fèi)的,而且第一個(gè)格子所需品梧桐木的價(jià)格1個(gè)銀子,第二個(gè)梧桐木是2個(gè)銀子,第三個(gè)是4個(gè)銀子。依次類推,意味著這些梧桐木的價(jià)格總和其實(shí)就是一個(gè)第一項(xiàng)為1,公比為2,項(xiàng)為35的等比數(shù)列。 當(dāng)用戶選擇購買梧桐木數(shù)量大于31時(shí),比如32-36中這些數(shù)字時(shí),這些等比數(shù)列的和就是大于2147483647。(只是舉例,實(shí)際上不會(huì)以這樣的價(jià)格出售物品)

在java中,4字節(jié)的存放int型變量的范圍是-2147483648至2147483647。在java、c的有符號(hào)int型中存儲(chǔ)時(shí),數(shù)的最高位描述符號(hào)位,4字節(jié)共32位,除去最高位的符號(hào)位,剩下31位,每個(gè)位上能表示2個(gè)數(shù)字,4字節(jié)的有符號(hào)的整數(shù)表示范圍為:負(fù)整數(shù)2^31個(gè),范圍為『-1至-2147483648』;正整數(shù)2^31個(gè),范圍為『2147483647至1』。 比如下圖(注意十進(jìn)制數(shù)字跟二進(jìn)制表示的變化順序):

 

 

當(dāng)開啟格子數(shù)字為大于31時(shí),比如32,那么所需費(fèi)用就是2147483647個(gè)銀兩,再買點(diǎn)其他物品,湊成超過2147483647的數(shù)字,比如又買了3個(gè)銀子的其他道具,總共花費(fèi)2147483650個(gè)銀子,在4字節(jié)的有符號(hào)int中表示出來的結(jié)果,變成符號(hào)位為1,即負(fù)整數(shù)。數(shù)值位為0000000 00000000 00000000 00000010,也就是10000000 00000000 00000000 00000010,對(duì)應(yīng)十進(jìn)制的-2147483646。程序邏輯上,再判斷現(xiàn)有銀兩是否足夠支付此筆花費(fèi)時(shí),是通過的。當(dāng)使用當(dāng)前余額減去這筆花費(fèi)時(shí),將變成減去一個(gè)負(fù)數(shù),那么實(shí)際上就是加上一個(gè)正整數(shù)。變成了自己銀兩賬戶余額的增長。而余額字段類型是long,則正確的存儲(chǔ)了這些余額,溢出漏洞被利用。在C中,使用無符號(hào)的數(shù)值類型,即可完成數(shù)值類型溢出刷錢的行為,但在java中,好像沒有無符號(hào)的類型。這也可以先確定所有參與計(jì)算的數(shù)值必須為正整數(shù)作為必要條件(游戲業(yè)務(wù)特性,游戲內(nèi)所有數(shù)字,肯定全為正整數(shù),甚至都不包括零),先做大小判斷,再做正正相加,不能得負(fù);負(fù)負(fù)相加,不能得正。來判斷是否發(fā)生了溢出問題。在PHP中,不用擔(dān)心溢出問題。

金幣復(fù)制-并發(fā)請(qǐng)求

Rpg類型的網(wǎng)頁游戲中,多數(shù)都有道具出售的功能,直接賣到商店,以及道具材料從商店買入功能。當(dāng)玩家同時(shí)針對(duì)買入、賣出兩個(gè)操作,瞬間大量并發(fā)請(qǐng)求時(shí),在服務(wù)器的處理邏輯一般有分別的兩個(gè)進(jìn)程處理,共享數(shù)據(jù)分別數(shù)據(jù)庫中的對(duì)應(yīng)賬戶余額表,如下圖:

 

 

webgame買入、賣出并發(fā)請(qǐng)求處理

//賣出
// startTrans
$iBalance = $obj->getBalance('user1'); //余額50
//UPDATE `role_gold` SET gold = 150 WHERE role_id = 1
if(!$obj->setBalance('user1',$iBalance + 100))
{
//rollback
}
//扣除物品
if (!$obj->delItems($items))
{
//rollback
}
//commit
//買入
// startTrans
$iBalance = $obj->getBalance('user1'); //余額50
//UPDATE `role_gold` SET gold = 0 WHERE role_id = 1
if(!$obj->setBalance('user1',$iBalance - 50))
{
//rollback
}
//發(fā)放物品
if (!$obj->addItems($items))
{
//rollback
}
//commit

賣出請(qǐng)求的處理進(jìn)程為1,買入請(qǐng)求的處理進(jìn)程為2。在進(jìn)程1還沒將結(jié)果寫入到DB時(shí),進(jìn)程2也從DB讀取到余額為50。這是,兩個(gè)進(jìn)程拿到的余額信息都是50。進(jìn)程1按照邏輯代碼,計(jì)算出剩余余額是150;進(jìn)程2計(jì)算出的剩余余額是0。最后,不管那個(gè)進(jìn)程最后寫入余額,都是錯(cuò)誤的結(jié)果。(注:這里的代碼邏輯操作,跟mysql事務(wù)無任何關(guān)系,事務(wù)只能保證單個(gè)進(jìn)程的事務(wù)范圍內(nèi)多條語句都正確執(zhí)行,或回滾。比如能保證扣錢成功,且物品刪除掉的兩個(gè)語句都正確執(zhí)行。能保證其中之一的語句執(zhí)行失敗時(shí),都正確回滾。)

其實(shí),在事物開啟時(shí)候,SELECT語句是否可以取到最新的數(shù)據(jù),或者是否需要等待鎖釋放,取決于MYSQL的事務(wù)隔離級(jí)別。在MYSQL的事務(wù)隔離級(jí)別中,有一下幾種隔離級(jí)別:

 

 

READ-UNCOMMITTED(讀取未提交內(nèi)容)級(jí)別

READ-COMMITTED(讀取提交內(nèi)容

REPEATABLE-READ(可重讀)

SERIERLIZED(可串行化)

對(duì)于READ-UNCOMMITTED,可以讀取其他事務(wù)中未提交的數(shù)據(jù),而且據(jù)說性能還高不到哪里去,幾乎沒有在實(shí)際應(yīng)用中使用;對(duì)于READ-COMMITTED,在同一事務(wù)中,會(huì)因?yàn)槠渌聞?wù)隨時(shí)可能有新的commit,導(dǎo)致同一select可能返回不同結(jié)果。這個(gè)也不適合游戲業(yè)務(wù);再說第四個(gè)SERIERLIZED,只要事務(wù)開啟,所有其他查詢,均排隊(duì)等待該事務(wù)提交之后,對(duì)于上面提到的賣出買入情況,第二個(gè)事務(wù)的SELECT操作,不會(huì)立刻返回,會(huì)處于鎖等待狀態(tài),一直到前一個(gè)事務(wù)結(jié)束。這個(gè)隔離級(jí)別,雖然能避免上面的問題,但性能較差,一般不會(huì)去使用。而REPEATABLE-READ隔離級(jí)別,也是mysql默認(rèn)的隔離級(jí)別,從功能上,比較符合游戲業(yè)務(wù)需要,也應(yīng)該是廣大webgame架構(gòu)中mysql的默認(rèn)隔離級(jí)別。

對(duì)于這個(gè)問題,你可能很快就給出解決辦法,把UPDATE語句改為UPDATE `role_gold` SET gold = gold + 100 WHERE role_id = 1或者UPDATE `role_gold` SET gold = 150 WHERE role_id = 1 AND gold = 100來解決,但這種多個(gè)事務(wù)同時(shí)操作修改多個(gè)表的多條記錄時(shí),還容易引發(fā)死鎖問題,比如《webgame中Mysql Deadlock ERROR 1213 (40001)錯(cuò)誤的排查歷程》。而且,當(dāng)條件為跨表內(nèi)數(shù)據(jù)是否存在,或者另外條件不在MYSQL中,而在其他網(wǎng)絡(luò)接口的響應(yīng)中時(shí),如何做呢?

金幣復(fù)制--邏輯漏洞

引用DNF的漏洞新聞 《利用網(wǎng)游漏洞狂刷游戲幣賺錢 玩家自曝3天賺17萬》

玩家曝出刷幣漏洞 一個(gè)游戲道具可刷400人民幣

該漏洞到底是什么?原來游戲中“云冪袖珍罐”這個(gè)道具,可以開出2件一樣的游戲裝備,還有極少幾率開出游戲幣,開出的裝備不值錢,但如果開出金幣了,則分為5000萬、8000萬以及1億游戲幣。而1億游戲幣,按正常市場行情,可在交易網(wǎng)上賣400多元人民幣。據(jù)玩家稱,在游戲中,角色的裝備是需要用包裹來存放的,不過目前角色的包裹最多只有48格,也就是只能存放最多48件裝備。漏洞就是利用包裹的有限空間,存放47件裝備(存放滿了又無法開罐子),只留下一格空位,而在開“云冪袖珍罐”出裝備時(shí),就會(huì)因包裹空間不足,而導(dǎo)致開罐失敗,而罐子還存在。玩家繼續(xù)開罐,直到出現(xiàn)金幣,但金幣不會(huì)占據(jù)包裹的空間,因此開罐成功,然后罐子消失。發(fā)現(xiàn)這個(gè)漏洞后,部分玩家狂刷游戲幣,然后馬上在第三方交易平臺(tái)出售游戲幣,兌換成現(xiàn)金。

這種問題,都是研發(fā)人員邏輯不嚴(yán)謹(jǐn)導(dǎo)致,這種問題,也較難發(fā)現(xiàn)。規(guī)避方式可以依賴下面提到的『運(yùn)營數(shù)據(jù)監(jiān)控』。

道具復(fù)制--背包整理

跟上面的賣出、買入一樣,同時(shí)穿裝備、整理包裹。在設(shè)計(jì)時(shí),可能會(huì)將身上裝備設(shè)計(jì)在裝備表中;將不在身上的裝備,設(shè)計(jì)到背包表中。當(dāng)同時(shí)進(jìn)行穿裝備跟整理包裹的請(qǐng)求并發(fā)時(shí),也會(huì)發(fā)生跟上面賣出,買入的情況,線程1讀取DB,發(fā)現(xiàn)包裹里有這裝備,然后準(zhǔn)備刪除背包表的這條記錄,當(dāng)準(zhǔn)備寫入到裝備表時(shí),另外一個(gè)整理包裹請(qǐng)求的線程來了,讀取了整個(gè)背包表,進(jìn)行道具的合并、排序。這時(shí),之前的線程將這個(gè)裝備寫入到裝備表,并刪除了背包表里的數(shù)據(jù),并提交事務(wù)。這個(gè)穿裝備的所有操作都是合理、正常,且正確執(zhí)行的。但另外一個(gè)整理背包的線程讀取了之前的背包表里的數(shù)據(jù),包括那件被穿上的裝備。在游戲中,整理背包需要對(duì)可堆疊道具做堆疊操作的,意味著需要合并多個(gè)道具,刪除部分道具。這意味著這里的操作,當(dāng)前cgi線程的內(nèi)存中的數(shù)據(jù),將都會(huì)以覆蓋的形式,寫入到DB中,那么意味著,之前被穿到身上的那件裝備,也會(huì)重新被寫入到背包中。那就變成兩張表里出現(xiàn)了兩個(gè)相同唯一ID的相同屬性的道具。玩家就可以把背包中的這個(gè)道具出售給其他玩家。

在java或者C之類程序中,數(shù)據(jù)放內(nèi)存中的游戲,也會(huì)存在這個(gè)問題,除非做讀鎖,但讀鎖會(huì)帶來鎖等待,鎖等待會(huì)導(dǎo)致線程被占用,阻塞后面請(qǐng)求的處理,堆積大量請(qǐng)求。導(dǎo)致系統(tǒng)負(fù)載升高,服務(wù)器繁忙,以至于無法響應(yīng)。好了,大約理解道具復(fù)制的形成原因了嗎?這個(gè)問題,我們從根本原因想想,問題到底出現(xiàn)在哪里?如何規(guī)避呢?細(xì)心的同學(xué)不難發(fā)現(xiàn),對(duì)于穿裝備的操作結(jié)果,會(huì)對(duì)下一個(gè)請(qǐng)求產(chǎn)生影響的,當(dāng)前操作未得到服務(wù)端響應(yīng)之前,服務(wù)端是不能處理下一個(gè)響應(yīng)的。對(duì)此,我們做了響應(yīng)處理鎖--『用戶并發(fā)請(qǐng)求鎖』。

用戶并發(fā)請(qǐng)求鎖的實(shí)現(xiàn),php中session以文件形式存儲(chǔ)時(shí),php會(huì)對(duì)session文件加鎖,不釋放(如果不特意執(zhí)行session_write_close),知道當(dāng)前響應(yīng)完成。另外一個(gè)線程才可以正常讀取,這簡介的形成了單個(gè)用戶的并發(fā)請(qǐng)求鎖,但是,后面的進(jìn)程一直處于等待狀態(tài),也會(huì)占用一個(gè)php-fpm進(jìn)程,阻塞其他用戶的正常請(qǐng)求對(duì)php線程的使用。為此,我們使用NOSQL的K-V形式結(jié)構(gòu),以u(píng)ser_name為key的形式,實(shí)現(xiàn)用戶并發(fā)請(qǐng)求鎖,第一個(gè)請(qǐng)求,生成這個(gè)k-v數(shù)據(jù),后一個(gè)請(qǐng)求發(fā)現(xiàn)有這個(gè)key了,那么立刻拋出異常,結(jié)束響應(yīng),F(xiàn)LASH根據(jù)異常內(nèi)容,提醒用戶不要進(jìn)行惡意操作。即不會(huì)發(fā)生并發(fā)請(qǐng)求,又不會(huì)阻塞請(qǐng)求處理。同時(shí),在請(qǐng)求結(jié)束的析構(gòu)函數(shù)里,對(duì)這個(gè)鎖進(jìn)行刪除操作,不影響下一個(gè)正常請(qǐng)求。若因?yàn)槌绦虍惓?,發(fā)生語法錯(cuò)誤,導(dǎo)致析構(gòu)函數(shù)沒法執(zhí)行,沒有刪除用戶鎖時(shí),可以在生成鎖的時(shí)候,設(shè)置過期時(shí)間,比如5秒,甚至2秒,利用nosql的過期機(jī)制,實(shí)現(xiàn)用戶解鎖,避免用戶長時(shí)間無法正常游戲。

類CC攻擊-多用戶共享資源鎖的timebomb

我們現(xiàn)在研發(fā)的項(xiàng)目,是以NOSQL Redis作為DB,來存儲(chǔ)數(shù)據(jù)的,redis并沒有成熟的事務(wù)處理機(jī)制,watch甚至算不上關(guān)系型數(shù)據(jù)庫中的事務(wù)處理。對(duì)此,更需要對(duì)表進(jìn)行加鎖解鎖。java之類語言的項(xiàng)目,很多都是直接操作內(nèi)存的,更是需要資源鎖,來解決并發(fā)問題,解決多個(gè)請(qǐng)求操作同一份數(shù)據(jù)的問題。公司有另外一個(gè)項(xiàng)目,出現(xiàn)過一次因?yàn)殒i的顆粒度較大,帶來的鎖等待timebomb的問題,也導(dǎo)致了線程繁阻塞忙,請(qǐng)求堆積,系統(tǒng)負(fù)載上升,導(dǎo)致宕機(jī)的問題。這個(gè)項(xiàng)目的鎖是針對(duì)所有用戶的鎖,每個(gè)用戶的請(qǐng)求發(fā)來時(shí),當(dāng)前線程會(huì)對(duì)所有用戶的數(shù)據(jù)加鎖,直到響應(yīng)完成,才釋放掉。這么做,是為了解決因當(dāng)前操作,會(huì)影響到其他用戶數(shù)據(jù),比如多人PK,多個(gè)玩家之間的交互。

 

 

當(dāng)其他請(qǐng)求一并發(fā)來時(shí),那么資源會(huì)立刻被鎖住,直到上一個(gè)請(qǐng)求結(jié)束,才釋放鎖,那么其他線程都處于等待狀態(tài)。用戶基數(shù)小時(shí),是看不出來鎖帶來的影響的,內(nèi)存操作都比較快。當(dāng)用戶基數(shù)大時(shí),或者說請(qǐng)求數(shù)增大時(shí),后面的請(qǐng)求的等待時(shí)間會(huì)越來越長,超過webserver的等待時(shí)間,直接返回timeout,不能正常提供服務(wù)。

這種問題的發(fā)生,是因?yàn)殒i的顆粒太大了,不應(yīng)該將所有用戶都鎖住,最好細(xì)化到當(dāng)前請(qǐng)求所影響到的單個(gè)用戶,只鎖住單個(gè)用戶的數(shù)據(jù)。這樣,才減少timebomb的發(fā)生。

其他

知乎里的朋友提到,很多webgame 的前端做了判斷,而后端沒做判斷的問題,這種問題,實(shí)屬不該存在。在我們的項(xiàng)目中,后端做的驗(yàn)證判斷,遠(yuǎn)比前端多的多。有時(shí)候,為了界面上的動(dòng)畫表現(xiàn),前端flash一般會(huì)在用戶操作之后,立刻渲染,然后,再根據(jù)后端響應(yīng),決定是否繼續(xù)做界面元素改動(dòng)。比如脫裝備,玩家操作時(shí),會(huì)先渲染裝備從角色面板,跳到背包里的動(dòng)畫,然后,再根據(jù)后端響應(yīng)結(jié)果,決定是否回滾動(dòng)畫。這樣,避免顯得操作后,一定時(shí)間的反映遲鈍假象,以提高用戶體驗(yàn)。當(dāng)然,后端是一定會(huì)做判斷的,判斷角色背包是否有空格之類?,F(xiàn)在的webgame研發(fā),一般都不會(huì)存在前端判斷,而后端不判斷的做法了。如果有,也應(yīng)該是個(gè)別遺漏情況。

比如去年的time33算法的hash dos的問題,使用json消息格式的webgame一定要注意,php只是在接收請(qǐng)求時(shí),做了最大數(shù)量的限制。但在json解碼之后的數(shù)據(jù)中,是沒有處理的。這里千萬別忘記了。

運(yùn)營數(shù)據(jù)異常監(jiān)控

再完善的防御措施,都仍會(huì)有安全漏洞。適當(dāng)?shù)谋O(jiān)控措施,也一定要有,監(jiān)控等級(jí)、金幣、游戲幣、經(jīng)驗(yàn)、珍貴物品的變化等等,一旦發(fā)現(xiàn),立刻報(bào)警,在漏洞未擴(kuò)散之前,第一時(shí)間去修復(fù)漏洞,以減少損失,維護(hù)游戲平衡。

日志系統(tǒng)

日志系統(tǒng)一定不能漏掉,所有操作,必須寫入日志,當(dāng)安全事件發(fā)生后,可以作為各種數(shù)據(jù)回滾,交易糾紛處理的可靠數(shù)據(jù)。也是作為數(shù)據(jù)監(jiān)控的最準(zhǔn)確的數(shù)據(jù)來源。

如果你用了我畫的小清新般的插圖,請(qǐng)記得為圖片寫上署名來源,畫圖是最花費(fèi)我時(shí)間的一件事。

覺得文章有用?立即: 和朋友一起 共學(xué)習(xí) 共進(jìn)步!

責(zé)任編輯:藍(lán)雨淚 來源: 中關(guān)村在線
相關(guān)推薦

2021-03-13 20:45:11

安全Web策略

2012-10-29 10:36:23

安全問題掃描策略云安全

2019-04-04 11:55:59

2012-07-09 09:41:43

2020-10-30 08:50:25

2023-06-14 11:59:55

2009-12-23 16:10:14

2021-04-22 21:58:51

云計(jì)算IaaS安全

2022-02-24 09:00:00

AD安全漏洞

2021-04-21 11:10:31

云存儲(chǔ)云安全數(shù)據(jù)泄露

2015-03-19 09:36:39

2023-07-14 08:50:37

2010-09-13 13:37:59

2020-04-10 08:34:58

網(wǎng)絡(luò)安全郵件安全網(wǎng)絡(luò)釣魚

2017-03-14 13:39:08

2021-04-20 10:54:47

云計(jì)算IaaS安全云安全

2021-08-02 18:08:53

網(wǎng)站安全SQL技術(shù)

2012-11-01 11:02:44

2019-02-27 07:35:01

惡意軟件數(shù)據(jù)泄露網(wǎng)絡(luò)防御

2013-04-02 13:06:20

BYODBYOD安全
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)