如何保證APP與服務端通信安全


前言
最近公司外包給別人做的一個APP項目上線了,拿到源碼一看那代碼質量真是一言難盡啊!

剛上線用戶比較少倒也沒出啥問題,不過隨着用戶慢慢變多,問題逐漸暴露出來了。

最嚴重的問題就是我們的APP與服務器的通信接口沒有加密處理被人抓包了,有人非法請求我們的接口獲取數據。

怎么處理這個問題呢?領導又把這個光榮而艱巨的任務分給了我,沒辦法只能硬着頭皮上啊,經過幾天摸索終於總結出了一套還算安全的APP與服務端通信的機制。

目錄
防非法調用——身份認證
防抓包——數據加密
防重放攻擊——時間戳+隨機字符串
防篡改——簽名機制
完整的Java解決方案
防非法調用——身份認證
身份認證指只有經過合法授權的用戶才能調用我們的接口,這里我們采用的是Token驗證機制。

APP與服務端的整個通信過程如下:

 

1.用戶首先需要輸入賬號密碼進行登錄;
2.APP帶上用戶輸入的賬號密碼請求服務端登錄接口;
3.服務端校驗賬號密碼,校驗成功返回一個唯一Token作為用戶身份憑證;
4.APP將Token緩存,同時登錄成功;
5.用戶使用APP瀏覽數據,APP每次向服務端請求數據時須同時帶上緩存的Token;
6.服務端收到請求,首先會校驗Token的合法性,校驗成功正常返回數據,校驗失敗直接返回錯誤;
Token驗證機制解決了什么問題?

設想一個場景,我們檢測到API接口正在被惡意調用,因為所有的接口都必須帶Token才能調用,根據Token我們就能快速反查到對應的用戶,所以Token驗證機制可以幫助我們快速確定調用者的身份。

發現惡意調用,我們通過Token確定調用者的身份后可以采取Token失效、封禁帳號等措施來阻止惡意調用繼續。

Token驗證機制能防止抓包嗎?

Token驗證機制並不能防止APP被抓包,因為Token同樣存在泄露的風險,惡意調用者只需要帶上Token再請求我們的API接口同樣還是能獲取到數據。

因為APP與服務端都是明文通信,一抓包就能看到請求參數以及返回數據,所以為了防止被抓包我們必須要對數據進行加密處理。

防抓包——數據加密
數據加密的過程,就是對原來明文傳輸的數據按某種加密算法進行加密處理,使其成為不可讀無意義的密文。

加密算法大體上可分為對稱加密、非對稱加密和散列算法等幾種方式,后面我們的方案都會涉及到。

對稱加密

對稱加密是一種可逆的加密算法,其中“對稱”的意思是加密過程和解密過程使用的是同一個密鑰。

 

 

常見的對稱加密算法有DES、3DES、AES、IDEA等。

使用對稱加密算法一次完整的加解密過程為:

APP與服務端事先約定好對稱加密的密鑰,各自保存;
APP使用密鑰將明文參數加密,再將密文發送到服務端;
服務端收到密文后使用同樣的密鑰對密文進行解密操作得到明文;
服務端同樣需要對數據進行加密之后才能返回給APP;
對稱加密算法的特點

對稱加密算法的特點是算法公開、計算量小、加密速度快、加密效率高。對稱加密算法的安全性依賴於密鑰,任何人只要拿到密鑰就能對數據進行加解密操作。

由於參與通信的雙方都需要持有密鑰,任何一方的秘鑰泄露,那么雙方的通信將無安全性可言,所以怎么安全的保存和傳遞密鑰是使用對稱加密最需要關注的問題。

非對稱加密

顧名思義非對稱加密指的是加密過程和解密過程使用不同的密鑰,非對稱加密算法需要一對密鑰(公鑰和私鑰),公鑰用來加密數據、私鑰用來解密數據。

 

常見的非對稱加密算法有RSA、ECC、ElGamal等。

非對稱加密一次完成的加解密過程為:

APP和服務端各自生成一對密鑰對(公鑰和私鑰),公鑰分別給到對方、私鑰自己保存;
APP使用服務端的公鑰對數據進行加密,然后將加密后的密文發送到服務端;
服務端收到密文后使用自己的私鑰進行解密得到明文數據;
服務端返回數據同樣需要使用APP的公鑰對數據進行加密;
非對稱加密算法特點

非對稱加密算法使用公鑰加密、私鑰解密,私鑰不需要公開傳輸所以安全性較高。同時私鑰可以對數據進行簽名、公鑰可以用來驗證簽名,可以解決中間人攻擊和信息被篡改的問題。

由於加解密過程使用不同的密鑰,所以對大量數據進行加解密運算的話速度是比較慢的,通常情況下非對稱加密算法只適合對少量數據進行加解密操作。

對稱加密算法運算速度快但安全性不足、非對稱加密算法安全性高但運算速度慢,那么我們的數據加密方案采用哪種加密算法呢?

既然兩種加密算法都有優缺點,那我們可以將兩者結合一下:用對稱加密算法加解密數據這樣可以保證運算速度,用非對稱加密算法加密對稱加密算法的密鑰這樣可以兼顧密鑰的安全性。

防重放攻擊——時間戳+隨機字符串
數據加密之后再進行通信雖然抓包之后看不到明文數據了,但是這並不能阻止不懷好意之人發起重放攻擊。

攔截到請求之后只需再原樣發送該請求到服務端就可以發起重放攻擊,如果接口內有一些查庫之類的比較耗性能的邏輯,那么在短時間內發起大量重放攻擊的話將會直接導致服務端崩潰。

怎么解決這個問題?

道理其實很簡單,我們只需要保證請求只能被正確處理一次即可,這里我們采用時間戳+隨機字符串的解決方案。

時間戳

我們在發送的數據里加入當前的時間戳,服務端在收到請求數據后首先取出時間戳與服務器當前時間進行比較,如果兩者相差超過一定時間(比如5分鍾),那么我們就認為本次請求超時,直接拒絕執行或返回錯誤就可以。

隨機字符串

我們在發送的數據中加入一個隨機生成的字符串,服務端在收到請求數據后首先在緩存中查找該字符串,如果在緩存中找到則認為這是一次重復請求直接拒絕處理,否則將該字符串加入緩存並繼續執行正確邏輯。

在請求中加入時間戳與隨機字符串之后,服務端收到請求后會首先對時間戳和隨機字符串進行校驗,校驗通過才會執行正常的業務處理邏輯。

防篡改——數字簽名
為了防重放攻擊,我們在數據中加入了時間戳與隨機字符串,但是別人在攔截到我們的請求之后也可以對時間戳和隨機字符串進行篡改,面對這種情況服務端要怎么分辨呢?

為了防止數據在傳輸過程中被篡改,我們引入數字簽名機制。

信息摘要算法

信息摘要算法(或者叫散列算法)是一種不可逆算法,任意長度的明文數據經過信息摘要算法計算后都可以得出一個固定長度的值(簽名)。

常見的信息摘要算法有MD5、SHA-1等。

詳細的簽名過程:

 

1.將數據密文、時間戳、隨機字符串以及私密的加鹽值一起進行信息摘要算法計算得到簽名值;
2.APP將數據密文、時間戳、隨機字符串以及簽名值一起發往服務端;
3.服務端收到數據后對數據密文、時間戳、隨機字符串以及加鹽值一起進行同樣的信息摘要算法計算,將計算出的簽名與數據中簽名進行對比,簽名一致證明沒有沒有被篡改;

為什么進行信息摘要計算要“加鹽”?

舉個例子就明白了,比如說123經過MD5計算后的簽名值是abc,那么就會產生123->abc這樣的對應關系,看到簽名值abc我就能反查到原值為123。如果有人收集並保存了足夠多的這種對應關系,那么就有可能從簽名值反推出原值。

這個時候加鹽操作就派上了用場,首先我們生成一個加鹽值qwe,這個加鹽值qwe並不會在網絡傳輸,只有通信雙方自己知道。

我們不直接計算123的簽名值,我們將加鹽值附加到123的后面得到123qwe,接着我們對123qwe進行MD5計算得到一個不一樣的簽名值def。

所以說即使原值一樣,但只要加鹽值不同那么最后得到簽名值就不一樣,這樣也就無法從簽名值反推出原值了。

完整的Java解決方案
因為我主要搞Java開發,所以就用Java語言實現了一套加解密方案,對稱加密采用AES算法、非對稱加密采用RSA算法,信息摘要算法采用MD5算法。

完整代碼執行流程:

 

下面分步驟進行詳細介紹:

准備工作:APP與服務端各自生成一對RSA密鑰對(公鑰和私鑰),公鑰給到對方、私鑰各自私密保存;

APP發送加密數據流程

1、生成一個隨機的AES算法密鑰;

2、使用服務端的RSA公鑰對AES密鑰明文進行加密得到AES密鑰密文;

3、對參數明文進行AES加密得到參數密文;

4、生成當前請求時間的時間戳;

5、為該次請求生成一個隨機字符串;

6、將參數密文、時間戳、隨機字符串和AES密鑰密文進行MD5計算得到md5值;

7、使用APP自己的RSA私鑰對md5值進行簽名得到簽名值;

8、將參數密文、時間戳、隨機字符串、AES密鑰密文和簽名值一起發送到服務端;

服務端解密數據流程

1、校驗時間戳與服務器當前時間的差值是否在合理的區間,超過則認為該次請求超時;

2、校驗隨機字符串是否已經在緩存中,如果已經在緩存中說明該次請求為重復請求,否則將該字符串加入緩存;

3、從收到的數據中取出參數密文、時間戳、隨機字符串和AES密鑰密文進行MD5計算得到md5值;

4、使用APP的RSA公鑰對計算得到的md5值和請求數據中的簽名值進行驗證,簽名驗證通過則說明請求數據沒有被篡改;

5、服務端使用自己的RSA私鑰解密AES密鑰密文得到AES密鑰明文;

6、使用AES密鑰明文對參數密文進行AES解密操作得到參數明文;

7、拿到參數明文之后進行正常的業務處理邏輯;

8、服務端數據需要經過同樣的加密操作之后才能返回給APP;

總結
APP與服務端肯定是要使用HTTPS協議進行通信的,再搭配上RAS+AES混合加密算法以及數字簽名機制,相信這套方案在絕大部分情況下是可以保證通信及數據安全的。

當然了,不排除APP有被人破解的可能,這種情況下任何加密機制都是白搭。但是不能說我們的加密機制就沒用了,我們只需要將破解我們APP的成本提高到一定程度就可以了。

這個道理其實就跟門鎖一樣,市面上絕大部分門鎖只要有時間都可以被開鎖的人打開,那你能說門鎖就沒有存在的意義了嗎?
————————————————
版權聲明:本文為CSDN博主「一個技術渣渣」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/kevinxxw/article/details/105603571


免責聲明!

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



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