• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 311, comments - 0, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            mangosd是MaNGOS-Zero項(xiàng)目中的游戲邏輯進(jìn)程,玩家一旦與realmd的keyexchange過(guò)程完成后(詳細(xì)內(nèi)容見(jiàn)《realmd認(rèn)證登錄服務(wù)器(一):認(rèn)證登錄基本流程》),便只與mangosd進(jìn)行交互。而客戶(hù)端與realmd的連接也會(huì)在客戶(hù)端向mangosd發(fā)送enterworld之后斷開(kāi)。

            本文將介紹客戶(hù)端連接到mangosd后,mangosd認(rèn)證客戶(hù)端合法性并最終建立RC4流加密的過(guò)程。具體過(guò)程如下:

             

            (1) 客戶(hù)端與mangosd建立TCP連接后,mangosd會(huì)向客戶(hù)端發(fā)送消息SMSG_AUTH_CHALLENGE

               1: int WorldSocket::open (void *a)
               2: {
               3:     ........
               4:  
               5:     // Send startup packet.
               6:     WorldPacket packet (SMSG_AUTH_CHALLENGE, 4);
               7:     packet << m_Seed;
               8:     if (SendPacket (packet) == -1)
               9:         return -1;
              10:  
              11:     ........
              12: }

            m_Seed是一個(gè)隨機(jī)數(shù),每次客戶(hù)端連接上來(lái)的時(shí)生成一個(gè)新的隨機(jī)數(shù)(隨著WorldSocket的創(chuàng)建而初始化)。

             

            (2)客戶(hù)端收到SMSG_AUTH_CHALLENGE消息后,知道服務(wù)器要求其提供身份認(rèn)證信息,于是開(kāi)始構(gòu)造CMSG_AUTH_SESSION消息。(以下代碼并非客戶(hù)端真實(shí)代碼)

               1: //client do auth
               2: {
               3:     BigNumber clientSeed;
               4:     clientSeed.SetRand(4 * 8);
               5:     sha.Initialize();
               6:     sha.UpdateData("abu");
               7:     uint32 t = 0;
               8:     sha.UpdateData((uint8 *)&t, 4);
               9:     sha.UpdateBigNumbers(&clientSend, NULL);
              10:     sha.UpdateData((uint8 *)&serverSeed, 4);
              11:     sha.UpdateBigNumbers(&K, NULL);
              12:     sha.Finalize();
              13:  
              14:     uint32 unk2;
              15:     ByteBuffer pktbuf;
              16:     string account = "abu";
              17:     uint16 pktbuf_size = 4+4+4+account.length()+4+20;
              18:     EndianConvertReverse(pktbuf_size);
              19:     pktbuf << uint16(pktbuf_size);
              20:     pktbuf << uint32(CMSG_AUTH_SESSION);
              21:     pktbuf << uint32(5875); //build version
              22:     pktbuf << unk2;
              23:     pktbuf << account;
              24:     pktbuf.append(clientSeed.AsByteArray(4), 4);
              25:     pktbuf.append(sha.GetDigest(), 20);
              26:  
              27:     send((char const*)pktbuf.contents(), pktbuf.size());
              28: }

            其中最為關(guān)鍵的是構(gòu)造20位的sha驗(yàn)證密文M:

            M = sha(t, account, clientSeed, serverSeed, K);

            t為0;account是明文的用戶(hù)名;clientSeed是由客戶(hù)端生成的隨機(jī)數(shù),用于本次連接游戲session;serverSeed是SMSG_AUTH_CHALLENGE消息發(fā)過(guò)來(lái)的服務(wù)器隨機(jī)數(shù);K是之前和realmd交互做keyexchange時(shí)生成的,由服務(wù)器和客戶(hù)端分別進(jìn)行計(jì)算,SRP6算法要求(保證)兩邊的計(jì)算結(jié)果一致,服務(wù)器端保存在realmd.account.sessionkey字段。

             

             

             

             

            (3)服務(wù)器收到客戶(hù)端發(fā)來(lái)的CMSG_AUTH_SESSION,首先對(duì)收到的數(shù)據(jù)包進(jìn)行分析,客戶(hù)端發(fā)來(lái)的數(shù)據(jù)包的包頭如下:

               1: struct ClientPktHeader
               2: {
               3:     uint16 size; //packet_size except itself
               4:     uint32 cmd;  //opCode
               5: };

            收到客戶(hù)端發(fā)來(lái)的data,處理流程可以簡(jiǎn)化為如下代碼:

            int WorldSocket::handle_input (ACE_HANDLE)

            {

            ……………

            handle_input_missing_data()

            {

            handle_input_header();

            handle_input_payload()

            {

            const int ret = ProcessIncoming (m_RecvWPct);

            }

            }

            }

            在ProcessIncoming()函數(shù)中使用switch case把客戶(hù)端發(fā)過(guò)來(lái)的不同的opcode定位到不同的處理函數(shù)中,而登錄認(rèn)證過(guò)程需要定位到int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)函數(shù)。

            在HandleAuthSession()函數(shù)中,服務(wù)器以客戶(hù)端相同的方式計(jì)算sha密文,并和客戶(hù)端傳來(lái)的做比較,如果相同則認(rèn)證通過(guò),然后創(chuàng)建WorldSession實(shí)例,初始化m_Crypt成員,以便以后服務(wù)器和客戶(hù)端之間交互的RC4對(duì)稱(chēng)加密使用。最后把新創(chuàng)建的WorldSession對(duì)象的m_Session添加到游戲世界中,添加完畢后,在游戲世界的主線(xiàn)程(Update線(xiàn)程)可以對(duì)該客戶(hù)端做相應(yīng)的處理。

             

            (4)HandleAuthSession()處理的最后會(huì)使用下面的代碼,進(jìn)行判斷:如果session可以作為normal_session的而不是queue_session則發(fā)送SMSG_AUTH_RESPONSE消息,至此所有發(fā)送的消息都將進(jìn)行RC4的流加密。

               1: void World::AddSession_ (WorldSession* s)
               2: {
               3:     ........
               4:  
               5:     if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
               6:     {
               7:         AddQueuedSession(s);
               8:         UpdateMaxSessionCounters();
               9:         DETAIL_LOG("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
              10:         return;
              11:     }
              12:  
              13:     // Checked for 1.12.2
              14:     WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4);
              15:     packet << uint8 (AUTH_OK);
              16:     packet << uint32 (0);                                   // BillingTimeRemaining
              17:     packet << uint8 (0);                                    // BillingPlanFlags
              18:     packet << uint32 (0);                                   // BillingTimeRested
              19:     s->SendPacket (&packet);
              20:  
              21:     ........
              22: }

             

            總結(jié):

             

             

            (1)realmd和mangosd在登錄認(rèn)證過(guò)程中,相互之間基本不通信,通過(guò)MySQL來(lái)傳遞client認(rèn)證所需的sessionkey。

            (2)每次客戶(hù)端和mangosd之間認(rèn)證時(shí),各自生成一個(gè)隨機(jī)數(shù)Seed,保證在傳輸過(guò)程中隱藏sessionkey。

            AV狠狠色丁香婷婷综合久久| 精品99久久aaa一级毛片| 久久精品夜色噜噜亚洲A∨| av无码久久久久不卡免费网站| 青青草原综合久久大伊人导航| 国产精品gz久久久| 大香网伊人久久综合网2020| 99久久精品九九亚洲精品| 99精品久久精品| 久久AAAA片一区二区| 人妻丰满?V无码久久不卡| 久久精品国产AV一区二区三区| 久久综合狠狠综合久久| 久久99国产精品久久久 | 国产精品无码久久久久| 久久久国产精品福利免费| 久久亚洲天堂| 伊人久久大香线焦AV综合影院| 午夜精品久久久久久99热| 国内精品久久九九国产精品| 成人免费网站久久久| 狠狠色伊人久久精品综合网 | 国产精品99久久久久久宅男| 99精品久久久久久久婷婷| 少妇久久久久久被弄高潮| 亚洲嫩草影院久久精品| 久久亚洲中文字幕精品一区| 亚洲色欲久久久综合网| 91精品免费久久久久久久久| 久久久久免费视频| 午夜精品久久久久久毛片| 精品国产一区二区三区久久蜜臀| 久久人人爽人人爽人人片av高请 | 国产∨亚洲V天堂无码久久久| 久久久久99精品成人片三人毛片| 精品久久人人爽天天玩人人妻| 亚洲嫩草影院久久精品| 日韩久久久久久中文人妻| 久久精品国产一区二区三区不卡| 好久久免费视频高清| 国产精品久久久久AV福利动漫|