文章主要講了移動api調用的受權和驗證問題,原文連接:The Ultimate Guide to Mobile API Security
android
移動API的使用是Stack Overflow和 Stormpath支持頻道上常常出現的話題。這是一個已經被解決的問題,可是須要大量必要的知識和充足的理解才能很好地實現。ios
這篇文章可以讓你瞭解到有關於在移動設備上安全的調用Restful API的一切內容,不管你是在構建一個須要訪問Restful API的移動app,仍是正在寫Restful API而且打算和移動app開發者進行交互。web
個人目標不只僅是解釋如何確保移動開發者可以安全調用你的Restful API,同時還解釋整個憑證從開始到結束的交換過程,以及如何從安全漏洞中恢復等等。數據庫
移動API安全問題api
在咱們投身去探究如何確保移動開發者可以安全調用Restful API以前,讓咱們先討論一下什麼使得移動認證有別於傳統的API認證。瀏覽器
API認證最基本的形式就是通常爲咱們所知的HTTP Basic Authentication。安全
對於API服務開發者和使用它的人來講,它的工做方式是很是簡單的:服務器
· 開發者會獲取到一個API key(通常是ID和Secret)。這個API key通常像這樣:3bb743bbd45d4eb8ae31e16b9f83c9ba:ffb7d6369eb84580ad2e52ca3fc06c9d。app
· 開發者有責任將API key存放在一個安全的地方,沒有人能夠獲得它。curl
· 開發者發起API請求時,須要把API key放到HTTP Authorization header中,同時帶有關鍵詞Basic(也就是用戶名和密碼都使用base64加密)。下面展現了開發者在調用API時如何指定API key進行認證,使用命令行工具cURL。
$ curl --user 3bb743bbd45d4eb8ae31e16b9f83c9ba:ffb7d6369eb84580ad2e52ca3fc06c9d https://api.example.com/v1/test
cURL工具能夠將獲取到的API證書用base64加密,而後建立一個HTTP Authorization hearder,以下所示:Basic M2JiNzQzYmJkNDVkNGViOGFlMzFlMTZiOWY4M2M5YmE6ZmZiN2Q2MzY5ZWI4NDU4MGFkMmU1MmNhM2ZjMDZjOWQ=.。而API服務器將會從HTTP Authorization hearder中獲取字符串,而後用base64解密,得到ID和Secret,驗證經過後再處理相應的API請求。
HTTP Basic Authentication雖然簡單,可是很好用。開發者在調用API時附帶API key能夠很好地與API服務器進行驗證。
可是,因爲移動app沒法安全存儲API祕鑰,使得HTTP Basic Authentication並非一個很好的選擇。同時,HTTP Basic Authentication要求在每次請求時使用原始的API keys,這就致使了keys會被長期使用,這是不安全的。
所以在大多數狀況下,這種驗證方式是不切實際的,由於沒法安全的將API keys嵌入到分配給許多用戶的移動app中。
好比說,你將API keys嵌入到你所構建的移動app中,然而一個精明的用戶可以對你app進行反向工程,獲取到keys,從而濫用你的API服務。
這就是爲何在不可信的環境中,HTTP Basic Authentication不是一個最好的選擇,例如web瀏覽器和移動app。
注意:和其餘全部認證協議同樣,HTTP Basic Authentication必須在SSL之上使用。
爲移動安全引入OAuth2.0
在此以前你可能據說過OAuth,而且在爭論它是什麼和它並無足夠的好。那麼讓咱們明確:OAuth2是一個優秀的協議,在不受信任的設備中用於保護API服務的安全。它經過一種咱們稱之爲token的認證方式來對移動用戶進行認證。
下面咱們從用戶的角度OAuth2 token認證的工做方式。
1. 用戶打開移動app,輸入帳號和密碼。
2. 移動app發送一個帶有用戶的用戶名和密碼的POST請求到API服務器,服務器進行驗證,成功後返回一個code。
3. 移動app經過code向認證服務器發送請求,認證成功後爲用戶生成一個一段時間後就會過時的access token。
4. 將access token存儲在移動設備本地,就像一個可以訪問API服務的API key同樣。
5. 一旦access token過時就再也不工做,須要再提示用戶輸入用戶名密碼,重複1的步驟。
之因此說OAuth2在保障APIs安全上是極好的,是由於咱們不須要在一個不安全的環境中長期存儲API keys,取而代之的是生成一個臨時的access tokens。這能夠抵禦一些潛在的攻擊。
如今,當您的API服務生成您的移動應用程序須要的Oauth2 token時,您固然須要將其存儲在您的移動應用程序中。
可是存在哪裏?!
token存儲的位置取決於你所處的開發平臺。若是你開發的是一個android app,你會將access tokens存儲在SharedPreferences中,若是你的IOS開發者,你將會將access tokens存在Keychain中。
若是你仍然存在疑問,下面這兩個Stack Overflow的posts可能會很是有用,它詳細闡述瞭如何在移動app中存儲access token。
· Where should I store access tokens on Android?
· Where should I store access tokens on iOS?
如今你應該對OAuth2有所瞭解,爲何要使用它,以及它的工做原理。
Access Tokens
讓咱們來討論一下access tokens。他們究竟是什麼?是一串隨機生成的數字?是uuid?仍是別的?
這是一個很好的問題。
這裏是一個比較短的答案:access token在技術上你任何你想要的字符串:
· 一個隨機數
· 一個隨機字符串
· 一個uuid
· 更多
更詳細的解釋:
· 爲客戶端而生成的。
· 驗證token的全部者是你(使用強的簽名)
·
存在過時時間。
有了以上的解釋,你可能會但願去遵照必定的規範。爲了避免本身處理這些,你能夠直接使用JWT(Json Web Token)。這是一個比較新的規範,容許你生成access token。這個規範(RFC7519)知足一下幾點:
· 能夠爲客戶端生成
· 能夠被建立者驗證
· 在某一具體時間後自動過時
· 能夠容納可變的JSON信息
· 無需查詢API服務,容許用戶本地驗證API憑證,從而減小對API調用的次數。
JWTs看起來像隨機生成的字符串,在使用的時候你能夠像字符串那樣存儲他們。這使得取代傳統的access token而使用JWTs很是方便,畢竟它們基本上都是相同的,而JWT有更多的優點。
JWTs老是以加密的方式被驗證。他們工做的方式以下:
· 在API服務器的某處存儲一個安全隨機字符串。通常是一個比較長的隨機字符串(40個字符左右差很少)
· 當你建立一個新的JWT時,你須要將這個隨機串傳遞個JWT類庫來簽署token,同時帶有一些你想存儲的數據,例如用戶ID,email等等。
· token將會被生成,看起來像header.claims.signature——header、claims和signature都是base64加密的字符串。
· 講生成的token給用戶,通常是API的使用者,例如移動app。
如今從移動客戶端中,你能夠看到存儲在JWT中的任何東西。so若是我有一個JWT,我能夠輕鬆地查看到裏面包含的JSON數據,一般以下所示:
{
"user_id": "e3457285-b604-4990-b902-960bcadb0693",
"scope": "can-read can-write"
}
固然,這是一個100%虛構的例子,可是你能夠從中知道,若是你獲得這個JWT的副本,你也能夠看到存儲在裏面的JSON信息。
JWT標準支持自動的過時標記,所以你也可以驗證這個JWT是有效的。不管你使用什麼開發語言,只要在使用JWT庫,你就能驗證JWT的有效性直到過時!
這意味着,若是你使用JWT訪問API服務,則只需驗證JWT,就能夠知道你的API調用是否能夠工做,不須要API調用。
如今,一旦你有了一個有效的JWT,你也能夠在服務器端用它作很酷的事情。
假設您已經向移動app發佈了一個包含如下數據的JWT:
{
"user_id": "e3457285-b604-4990-b902-960bcadb0693",
"scope": "can-read can-write"
}
假設移動app上有惡意代碼可以修改你的JWT,好比說:
{
"user_id": "e3457285-b604-4990-b902-960bcadb0693",
"scope": "can-read can-write can-delete"
}
若是這個修改過的token被髮送到咱們的API服務器會發生什麼?它會起做用嗎?咱們的服務器會接受這個修改的JWT嗎?
注意!!
當你的API服務收到JWT並進行驗證時,它會作如下幾件事情:
· 經過使用只有服務器才知道的隨機生成的字符串來檢查token,確保它沒有被篡改。若是JWT徹底被修改,這個檢查就會失敗,你會知道有人正在試圖作一些使人討厭的事情。
· 同時服務器會檢查JWT的過時時間,確保它的合法性。so若是客戶端用一個已通過期的token來進行請求,你能夠馬上拒絕。
這是很好的功能,由於它使處理驗證/到期/安全更簡單。
在使用JWTs時,你惟一須要記住的就是:不要在JWT中存儲敏感信息。
謹記以上提到的規則,那麼在使用JWTs時就不會出錯了。
一般你會存一下兩條信息在JWTs中:
· 用戶賬戶的某種惟一ID。這樣,當您收到此JWT進行身份驗證時,您能夠從用戶數據庫中查找此用戶。
· 用戶權限。固然若是構建的是全部用戶都能訪問的簡單的API,那麼這個多是沒必要要的。可是經過這個,用戶就不須要經過看API文檔來了解本身能夠作什麼,不能夠作什麼,只須要根據看本身的JWT就能夠。
以上就是有關於JWT的所有。