1. 程式人生 > >WebAPI常見的鑒權方法,及其適用範圍

WebAPI常見的鑒權方法,及其適用範圍

安全 cat 足夠 是否 註入 前端 單純 它的 申請

在談這個問題之前,我們先來說說在WebAPI中保障接口請求合法性的常見辦法:

  • API Key + API Secret
  • cookie-session認證
  • OAuth
  • JWT

當然還有很多其它的,比如 openid connect (OAuth 2.0協議之上的簡單身份層),Basic Auth ,Digest Auth 不一一例舉了

1、API Key + API Secret

Resource + API Key + API Secret 匹配正確後,才可以訪問Resource,通常還會配合時間戳來進行時效控制。這種鑒權方式有以下特點:

1)API Key / API Secret這種模式本質是不是RBAC,而是做的ACL訪問權限控制用的。

2)服務器負責為每個客戶端生成一對 key/secret ( key/secret 沒有任何關系,不能相互推算),保存,並告知客戶端。

3)一般是把所有的請求參數(API Key也放在請求參數內)排序後和API Secret做hash生成一個簽名sign參數,服務器後臺只需要按照規則做一次簽名計算,然後和請求的簽名做比較,如果相等驗證通過,不相等就不通過。

4)為避免重放攻擊,可加上 timestamp 參數,指明客戶端調用的時間。服務端在驗證請求時若 timestamp 超過允許誤差則直接返回錯誤。

5)一般來說每一個api用戶都需要分配一對API Key / API Secret的,比如你有幾百萬的用戶,那麽需要幾百萬個密鑰對的,數據量不大時一般存在xml中,數據量大時可以存在mysql表中。

優點:

1)實現簡單。

2)占用計算資源和網絡資源都很少。

3)安全性較好。

缺點:

1)當API Key / API Secret足夠多時,服務端有一定的存儲成本

2)鑒權本身不能承載其它的信息,服務端只能通過API Key來區別調用者。

3)API Secret一旦泄密,將是致命的。

適用範圍:

事實上,這種模式適用於大多數的WebAPI,除非你需要在token中承載更多的信息,或者你的API Key / API Secret足夠多,多到能影響你服務端的布署。

2、cookie-session認證

這是比較老牌的鑒權方式了,這種鑒權方式有以下特點:

1)為了使後臺應用能識別是哪個用戶發出的請求,只能在後臺服務器存儲一份用戶登陸信息,這份信息也會在響應前端請求時返回給瀏覽器(前端),前端將其保存為cookie。

2)下次請求時前端發送給後端應用,後端應用就可以識別這個請求是來自哪個用戶了。

3)cookie內僅包含一個session標識符而諸如用戶信息、授權列表等都保存在服務端的session中。

優點:

1)老牌,資料多,語言支持完善。

2)較易於擴展,外部session存儲方案已經非常成熟了(比如Redis)。

缺點:

1)性能相於較低:每一個用戶經過後端應用認證之後,後端應用都要在服務端做一次記錄,以方便用戶下次請求的鑒別,通常而言session都是保存在內存中,而隨著認證用戶的增多,服務端的開銷會明顯增大。

2)與REST風格不匹配。因為它在一個無狀態協議裏註入了狀態。

3)CSRF攻擊:因為基於cookie來進行用戶識別, cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊。有興趣可以看下http://www.uml.org.cn/Test/201508124.asp 。

4)很難跨平臺:在移動應用上 session 和 cookie 很難行通,你無法與移動終端共享服務器創建的 session 和 cookie。

適用範圍:

傳統的web網站,且同時認證的人數不是足夠大(是足夠大)的都可以用這種方式,事實上,這種方式現在依舊在很各大網站平臺上活躍著。

3、OAuth

OAUTH協議為用戶資源的授權提供了一個安全的、開放而又簡易的標準。與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到用戶的帳號信息(如用戶名與密碼),即第三方無需使用用戶的用戶名與密碼就可以申請獲得該用戶資源的授權,因此OAUTH是安全的。oAuth是Open Authorization的簡寫。這種鑒權方式有以下特點:

1)OAuth在"客戶端"與"服務提供商"之間,設置了一個授權層(authorization layer)。

2)"客戶端"不能直接登錄"服務提供商",只能登錄授權層,以此將用戶與客戶端區分開來。

3)"客戶端"登錄授權層所用的令牌(token),與用戶的密碼不同。用戶可以在登錄的時候,指定授權層令牌的權限範圍和有效期。

4)"客戶端"登錄授權層以後,"服務提供商"根據令牌的權限範圍和有效期,向"客戶端"開放用戶儲存的資料。

優點:

1)簡單:不管是 OAUTH 服務提供者還是應用開發者,都很容易於理解與使用。

2)安全:沒有涉及到用戶密鑰等信息,更安全更靈活。

3)開放:任何服務提供商都可以實現 OAUTH ,任何軟件開發商都可以使用 OAUTH 。

缺點:

1)需要增加授權服務器。

2)token載體信息單一,不利於服務端對調用者的統計等操作。

適用範圍:

常用於用戶的授權,如使用QQ在其它網站上快速登錄。很明顯沒有第三方參與的場景是不適合用 OAuth 的,這種情況可以使用API Key + API Secret或JWT。

關於OAuth的詳細介紹,可以看大牛的文章 《理解OAuth 2.0》

4、JWT

這種鑒權方式有以下特點:

1)JWT常常被用作保護服務端的資源(resource)。

2)客戶端通常將JWT通過HTTP的Authorization header發送給服務端。

3)服務端使用自己保存的key計算、驗證簽名以判斷該JWT是否可信。

4)在Web應用中,別再把JWT當做session使用,絕大多數情況下,傳統的cookie-session機制工作得更好。

4)JWT適合一次性的命令認證,頒發一個有效期極短的JWT,即使暴露了危險也很小

5)由於每次操作都會生成新的JWT,因此也沒必要保存JWT,真正實現無狀態。

優點:

1)易於水平擴展(當訪問量足夠在時,相對於cookie-session方案而言的。如果把session中的認證信息都保存在JWT中,在服務端就沒有session存在的必要了。當服務端水平擴展的時候,就不用處理session復制(session replication)/ session黏連(sticky session)或是引入外部session存儲了)

2)無狀態。

3)支持移動設備。

4)跨程序調用。

5)安全。

6)token的承載的信息很豐富。

實事上,所有使用token的模式,都是無狀態、跨程序調用的。

缺點:

1)如果JWT中的payload的信息過多,網絡資源占用較多。

2)JWT 的過期和刷新處理起來較麻煩。這個可以參考業界主流做法,AWS、Azure 和 Auth0 都是用 JWT 為載體,ID Token + Access Token + Refresh Token 的模式:
https://docs.aws.amazon.com/zh_cn/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html
https://docs.microsoft.com/zh-cn/azure/active-directory/develop/active-directory-token-and-claims

適用範圍:

JWT(其實還有SAML)最適合的應用場景就是“開票”,或者“簽字”。

例如:員工張三需要請假一天,於是填寫請假條,張三在獲得其主管部門領導簽字後,將請假交給HR部門李四,李四確認領導簽字無誤後,將請假條收回,並在公司考勤表中做相應記錄。這樣張三就可以得到一天的假期,去浪。

在以上的例子中,“請假條”就是JWT中的payload(載荷就是存放有效信息的地方),領導簽字就是base64後的數字簽名(signature),領導是iss(issuer / jwt簽發者),“HR部門的李四”即為JWT的aud(audience / 接收jwt的一方),aud需要驗證領導簽名是否合法,驗證合法後根據payload中請求的資源給予相應的權限,同時將JWT收回。

總結

不要單純的為了用某種鑒權方式而去強行使用,可以根據實際需要進行修改、擴展,或者是幾個模式進行組合。總之,沒有最好的,只有最適合的。

WebAPI常見的鑒權方法,及其適用範圍