最近做的金融項目,app調用的接口需要做一個身份認證,所以找了下目前API services驗證的幾種方式。之前翻譯的一篇文章——[譯]移動API安全終極指南中,主要提出了API服務調用驗證的問題,通過添加認證,防止API濫用。里面提到了基本的HTTP Basic Authentication、OAuth2.0以及JWT這三種驗證方式,同時對這三種認證技術的原理做了大致的梳理。那么這篇文章主要介紹一下這幾種認證方式的使用環境以及別的一些方法用於API接口調用認證。
下面就列舉一些常見的認證方式和應用,有些大廠的驗證方法和常見的驗證協議是值得我們學習的。
1. 類似HTTP Basic Authentication
隨意在網上搜索公共API服務,比如下圖中的百度基站查詢的接口。
這種接口一般付費之后會獲取到一個apikey,通過apikey進行請求。和HTTP Basic Authentication類似,需要把apikey這個字段寫入HTTP header中,服務器驗證后,返回相應的結果。
總結:也許是因為公共api的原因吧,所以驗證的方式比較簡單。下面會講到,同樣是百度的api,在獲取地理數據方面,驗證方式會嚴格很多。當然即便是有人惡意抓包獲取到付費用戶的apikey,也不會造成太大的危害。這類型的接口一般都有當天最大的請求次數,同時用戶也很容易發現。
參考:
2. 百度LBS接口加密的方式
上圖是百度地圖中的API服務,通過IP來獲取獲取位置信息。
他的加密方式如下:
首先,購買了此服務的開發者會拿到ak(apikey)和sk(secretkey)。接口調用時除了公共參數之外,還需要ak和sn兩個參數。sn是一個用特定算法生成的加密串。
sn生成算法
- url后的參數根據鍵值的字典排序(get不需要),拼接成字符串,utf-8編碼。
- 拼接sk后再utf-8編碼
- md5編碼。
服務器接收到參數后,通過開發者的ak獲取到sk,再根據上述操作,生成sn進行比對,驗證通過后,調用相應的接口返回結果。
總結:這種方法提到了ak和sk,有一種RSA的味道,安全性顯然比上一種強很多。由於私鑰是不傳播的,只要做好秘鑰管理,應該還是比較難破解的。
參考:
3. OAuth2.0
原理不多講,兩次握手獲取認證,授權獲取相關資源。好像app上用到的不多,最多的應用是在復雜系統的單點登錄和第三方登錄上(可參考微博、QQ登錄,微信公眾號授權等)。
參考:
4. 類似OAuth2.0的access_token和refresh_token
熟悉OAuth2.0的開發者都知道,整個授權流程。
- 授權獲取code。
- 通過code獲取access_token和refresh_token。
- 根據access_token請求資源。
那么問了杭州某移動互聯網公司的小伙伴他們認證方案。結果就是簡化版的OAuth2.0。
- 用戶登錄后,后台簽發access_token和refresh_token。
- access_token過期后使用refresh_token進行刷新。
- refresh_token過期,app提示重新登錄。類似OAuth2.0的重新授權。
5. JWT
JSON Web Token,2015年出的一個標標准(RFC 7519)。
JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.
簡單來講就是一個加密串,和傳統的token不同,這個加密串不是nosense,而是可以解密成兩段json數據。加密串如下所示,點分三段式結構。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
解密后分為兩段json:
{
'typ': 'JWT',
'alg': 'HS256'
}
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
綜上JWT的形式是這樣的:
[json1 base64加密].[json2 base64加密].[(json1加密后+json2加密后+secret) sha256加密]
總結:詳細的原理可以看那篇我翻譯的文章。那么和傳統的token相比就很有優勢了。當移動app登錄,API服務器獲取用戶的ID加上過期時間等信息生成JWT,簽發給app。下次app調用API附帶JWT,服務端解析后,返回結果。由於所有的信息都存在JWT中,也就不需要使用數據庫存儲和查詢,這些額外的開銷了。
參考:
總結
目前看到的認證方式基本上就是以上這幾種,當然還有上述幾種的組合,例如OAuth2.0+JWT。服務器對API的使用者進行認證,雖然增加了一定的工作量,但是對整個系統的安全性還是有提高的。