鵝廠乾貨 | 騰訊遊戲APP協議迭代的那些事

歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~。
android

做者:羅廣鎮 | 騰訊移動開發工程師web

App與後臺通訊一般有采用json等文本協議或者採用二進制協議,本文則主要總結了心悅俱樂部App的接入層從文本協議到二進制jce協議迭代過程當中的技術方案,包括協議規範、安全性等方面的內容。算法

背景

在移動客戶端開發中,基本都會須要與服務端進行數據交互。對於通常的App來講,經過http請求,採用json格式的文本協議進行數據通訊也就基本知足需求了。在業務不斷增長,用戶體量不斷增加以後,對用戶體驗的要求也愈來愈高。對於須要進行頻繁網絡請求的App來講,提升網絡傳輸性能則是提升App響應速度,優化用戶體驗的重要手段。所以每每會引入二進制協議,來減少數據包。本文則主要總結了心悅俱樂部App的接入層從文本協議到二進制jce協議迭代過程當中的技術方案,包括協議規範、安全性等方面的內容。json

文本協議方案

在http的數據請求中,通常會採用json或者xml形式的文本協議。特別是對於App或者web端的先後臺交互更多的會採用json格式,數據量相對xml較小,協議字段能夠增刪改,比較靈活。後端

心悅App在前期,Native模塊與內嵌H5和WEB管理端使用的都是統一的PHP框架後臺,採用的是http+json的文本協議接入層。api

請求與響應

App網絡層發起http請求時,通常會對http header作一些定製修改,來傳遞一些通用數據,一般會在User-Agent寫入一些App和手機的信息,例如操做系統版本、機型、App版本等等,在cookie中寫入登陸態。數組

例如:User-Agent:tgclub/4.1.0.63(OPPO R7;android 4.4.4;Scale/480;android;868979027609987)複製代碼

在文本協議方案中,不一樣的網絡請求能夠由不一樣的請求路徑區分,路徑格式以下:安全

http://xxx.xxx.com/xyapp/api/{mod}/{act}?c_ver={version}bash

version:協議版本號, 默認當前版本號碼爲1.0服務器

mod:模塊名稱

act:動做名稱

如,獲取遊戲信息,接口名稱爲 game/get_game_info,地址爲:http://xxx.xx.com/xyapp/api/game/get_game_info

請求響應數據都包含在返回的JSON中,按照與後臺定義好的協議字段返回。通常建議包括本次操做的返回碼、錯誤碼和具體的業務數據。心悅App的響應 JSON 中,包含字段有: - status 返回碼,1成功 0失敗 - data 返回業務數據,當發生內部錯誤時,會返回字段errcode,例如

{"status":0,"errcode":10002,"data":"簽名校驗錯誤"}:複製代碼

能夠看到,雖然json數據的格式已經很簡潔了,但它依然把屬性名稱,好比 status和data, 以及大括號,引號這些用於表示數據格式的信息也進行傳輸了,數據存在較多冗餘。

安全性

因爲文本協議結構清晰、意義明確,因此方便解讀,但也存在較大的安全風險。對於App後臺服務來講,也容易存在API泄漏,第三方客戶端僞造訪問服務器對咱們的服務或者流程形成安全危害。所以須要必定的安全校驗和加密措施。

首先,接入層要驗證請求的合法性,心悅App文本協議方案中採用的是校驗簽名的方式來驗證發來的請求是否來自官方客戶端和是否有效。

HTTP調用需以GET形式傳遞一下兩個參數:簽名參數(sn)和時間戳(time_st)。

簽名參數的生成方式:首先對http請求中的全部參數按照參數名的字典順序排序,參數名和參數值拼接成字符串,再用每一個設備獨有的簽名密鑰sn_key對該字符串取md5值獲得簽名參數(sn)的值。其中籤名密鑰sn_key,由後臺根據用戶設備id生成,經過簽名註冊接口從服務器獲取,後臺和客戶端分別存儲。簽名註冊接口則用預先與App約定好的初始密鑰進行簽名校驗,保證簽名安全性。簽名的參數包括全部的get參數和post參數。後臺收到客戶端請求後用一樣的簽名方式計算sn參數,與請求中的參數一致纔對請求進行處理。此外,對於時間戳參數,服務器會拒絕必定時間範圍以外的請求,防止請求重放攻擊。

例如請求request爲:?param_b=1&param_a=2&time_st=123,sn_key=aaa

那麼簽名參數sn = md5('param_a2param_b1time_st123aaa')

其次,若要保證請求數據中的敏感內容不被泄露,須要對文本協議內容進行加密傳輸活採用https協議。在心悅App的文本協議方案中,採用的是對請求數據進行CBC模式的AES加密。AES加密是一種對稱加密算法,同一個密鑰能夠同時用做信息的加密和解密。加密密鑰pub_key能夠經過簽名註冊接口和sn_key一併返回,後臺和客戶端分別存儲pub_key用於加密解密。簽名註冊接口可使用客戶端和服務器約定初始密鑰加密解密,而且這個密鑰只在簽名註冊接口用一次。

通過簽名校驗和數據加密以後,基本上能夠保證文本協議網絡請求的安全性。

二進制協議方案

二進制協議在網絡傳輸中也有普遍使用,具體的協議也有不少,例如公司自研的jce協議,谷歌的Protocol buffer等等。

爲優化App的網絡請求速度和減少數據包大小,並配合接入層後臺往C++框架改造,心悅App的接入層網絡數據傳輸協議切換成了二進制協議。協議數據包的定義統一採用協議頭+業務包體(協議內容)的方式,協議頭中用若干比特位定義協議版本號、數據包長度等信息。

請求與響應

在二進制協議方案中,不一樣的網絡請求使用同一域名,後臺根據請求結構體中的命令字參數進行路由轉發。因爲客戶端的數據集合需求比較多樣,後臺則通常爲服務化接口,所以須要支持多命令字請求合併,數據一併返回。此外,爲進一步減少網絡傳輸數據包,協議能夠考慮進行壓縮,同時爲保證數據安全性,數據加密也必不可少。綜上,心悅App在進行二進制協議改造時,制定了以下格式的二進制協議格式:

請求協議

響應協議

請求協議的協議頭中包含業務標誌、協議版本號和數據包長度,服務端只處理以業務標誌開頭的數據包。截取協議頭後,用PkgReq結構體解析協議頭中指定長度的數據包。PkgReq包括明文的協議包頭PkgReqHead和密文的二進制流。PkgReqHead中會包括客戶端生成的請求序列號,密文的加密方式、壓縮方式等信息,用這些信息解開加密壓縮過的PkgReqBody。PkgReqBody包含通用請求數據ReqHead和業務請求數據ReqBody數組。ReqHead中主要包括用戶的設備信息、App版本信息、帳號信息、網絡環境等等基礎信息,ReqBody則是具體請求命令字和業務請求結構體的封裝。如果多個命令字的合併請求則會有多個ReqBody,而ReqHead只須要有一份。後臺路由層根據ReqBody中的命令字cmdid將ReqBody中的businessReqBody字段轉發到具體的後臺服務進行處理。而且ReqHead中設計了guid字段,後臺會存儲用戶的設備信息而且給用戶分配惟一的guid,客戶端拿到guid以後,後續的請求就不須要上報不變的設備信息字段,只須要上傳guid,後端能夠根據guid按需獲取用戶設備信息,減少請求數據量。

響應協議與請求協議的總體結構相似,因爲響應須要返回錯誤碼或返回碼給客戶端,而且存在合併請求,所以設計了兩層返回碼。在RspHead中有總體返回碼iRet,做爲路由層總體的處理結果;每一個RspBody中還有ret,做爲該命令字對應的後臺服務的返回結果。每一個RspBody中的businessRspBody在iRet和ret同時有效時才能用該命令字對應的響應結構體進行解包。

此外,命令字須要定義在枚舉中,命令字命名與協議中業務請求結構體和業務響應結構體命名保持對稱,如GetSettingRequest對應GetSettingResponse,命令字爲命令字爲GetSetting=1001,便於用命令字進行反射匹配出請求和響應。具體的Request結構體和Response結構體示例:

安全性

二進制協議方案與文本協議方案相似,都須要考慮數據安全性的問題。二進制協議因爲傳輸的數據包是二進制流,抓包並不能直接看到結構體,例如咱們採用的jce協議,必須知道完整的數據格式才能解析出原始數據。在咱們的方案中還採用了https、對協議中的內容數據PkgReqBody/PkgRspBody進行先壓縮後加密等操做保證安全性。

在心悅App的二進制協議方案中,採用的也是AES加密,與文本協議不一樣的是採用AES的GCM模式。AES做爲一種分組對稱加密算法,須要對明文進行分組,分組長度可爲128或256bits,有ECB,CBC,CTR等多種模式,這裏不作具體介紹。GCM模式能夠提供對消息的加密和完整性校驗,具體原理這裏不做詳細介紹,能夠參考文章 什麼是 AES-GCM加密算法。AES-GCM加密也須要密鑰key、初始向量iv,而且加密以後除了獲得密文,還會獲得消息校驗碼。在數據接收方能夠經過這個校驗碼校驗密文是否有篡改。在具體實現中,爲加強安全性,iv由請求序列號和key按照必定規則動態生成,並將加密獲得的校驗碼填寫在協議包頭PkgReqHead/PkgRspHead中,在解密時須要做爲驗證條件。

在安卓客戶端,對數據進行加密、壓縮的操做封裝在了NDK代碼中,經過提供so庫的方式給Java層調用,而且校驗App簽名、應用包名,防止反編譯,能夠進一步保證了安全性。

小結

對於App和後臺接入層的數據交互,不論是長連接仍是短連接,其數據協議均可以存在文本協議和二進制協議兩種類型。文本協議直觀、描述性強,容易理解、便與調試,而且協議修改方便,可是數據冗餘較多,安全性稍差;二進制協議格式精簡、冗餘數據少,竊聽成本更高,可是數據不直觀、調試略微複雜,使用、升級維護都須要約定好規則,各有優劣,所以能夠根據不一樣的使用場景肯定不一樣的方案。

問答

DevMaster與DevOps區別與做用?

相關閱讀

移動互聯網IM之協議設計
http超文本協議,讓http再也不難懂
http超文本協議,讓http再也不難懂(二)

此文已由做者受權騰訊雲+社區發佈,轉載請註明文章出處

原文連接:https://cloud.tencent.com/developer/article/1070247

相關文章
相關標籤/搜索