當前位置:
首頁 > 最新 > 通用安全的token化解決方案

通用安全的token化解決方案

一、協議過程

a. 我們先來看token化的協議過程

圖 一.a

在用戶輸入正確的用戶名和密碼後,"圖 一.a" 中 Step "2." 將tokens放入到cookie中, 拿點融舉例子,我們會將cookie放到 ".dianrong.com」這個域名下。看起來非常簡單,認證、單點登陸全都有了。

b. 我們再來看一看CAS的SSO協議過程

圖 一.b

圖 一.b 描述了開源應用CAS定義的單點登陸協議

有重定向、有指定service, 臨時ticket傳遞、有後台有狀態ticket的驗證,整個流程步驟比較多。倘若我們的應用是單頁的前後端分離應用,前端和後端僅通過ajax進行訪問,在重定向這一步會卡住。

點融的應用幾乎都是前後端分離,我們針對這種情況做了一些定製(本文重點不是這個, 有興趣可以找作者)。

通過這個協議過程的對比,我們發現,token無疑提供了更高的便捷性。

二. Token化的優點和缺點

優點:

? 無狀態、性能——token機制在伺服器端不需要存儲session信息,因為token自身可包含登陸用戶的信息,例如 手機號、用戶id,在客戶端cookie存儲這個信息從性能上來講, 節省一次網路,僅做一次token的驗簽,將io消耗轉換為cpu消耗.

? 解耦—— token在內網生成,可由任意一個集成了SDK的伺服器端 設置到客戶端,它的生成 和 驗證方案可隨意切換,中心伺服器用於維護狀態

? 適用於現代Clients—— 比如微信小程序、比如原生平台

? 便捷 ——集成方便、測試方便、客戶端透明

? 標準 ——比如RFC7519,使用JWT格式,可以跨平台

ps: token化之後,token理論上可以交給前端,由前端自己決定保存方式、傳遞方式,也因此可以實現跨域變得更加方便方式。 但由此而引出的安全問題後端無法掌控,因而我不認為跨域訪問是一個優勢, 跨域的授權, 應該由oauth2.0協議來完成。

缺點:

? Security—— 便捷 和 安全是一對好夥伴,在獲得便捷的同時應當考慮安全性是否下降

? Revoke token—— token無狀態,屬於Bearer Token 因此無法對已經簽發的token進行撤銷, 只能等待其失效.

? Renew token—— token無狀態,所以不會像session隨著每一次的訪問而修改session失效時間.

三、平衡缺點,獲得優點

A. Security

為了儘可能的限制安全問題發生的範圍,我們生成的所有token都會放入cookie並且cookie.setMaxAge(-1), 常見的security問題以及其解決方案:

1. Man-in-the-Middle.使用https加密,避免中途有人監聽竊取cookie, 以java代碼為例, cookie new出來之後需要 setSecure=true, 只在https的情況下設置cookie.

2. Cross-Site Scripting (XSS), cookie new出來之後需要 setHttpOnly=true, 這樣js代碼就無法操作cookie, 自然XSS無處遁尋。針對伺服器端 和 非WEB客戶端,則需要分別保證自己依賴的library不包含可執行代碼,客戶端保證伺服器返回的任何內容都有執行類似escapeHtml的操作.

3. Cross-Site Request Forgery (CSRF), 在訪問某些比較敏感介面時(比如轉賬),使用Double-Submit Cookie方案解決。 這個安全問題有一點需要注意:不要濫用CORS(cross origin resource share), 這樣會導致 CSRF方式的漏洞, 完全暴露給惡意攻擊者。

B. Renew & Revoke token

想要克服無狀態的這兩個缺點,首先看 兩個概念 : Access & refresh token簽名tokens

? Access token擁有比較短的生存時間, 可以被認作為一個無狀態的可信任的字元串。

? Refresh token擁有比較長的生存時間,是用來換取access token的。refresh token應該可以被撤銷(Database + cache).

基於這兩個從oauth2借來的概念,我們的方案如圖:

圖 三.a server-side use case

圖 三.b client-side 流程圖

如圖三.b, 我們將refresh token有狀態化,通過對refresh token的控制,從而達成對token renew&revoke的目的。

通過Access Token & Refresh token pair 的有效期的配置,我們即擁有了token無狀態的優勢(由access token提供),也擁有了控制token狀態的能力。

以下舉一些常見的token可配置的例子:

? 敏感應用(如 銀行app)

Access token TTL(Time to live) : 1 minute

Refresh token TTL : 30 minutes

? 普通應用

Access token TTL: 5 minutes

Refresh token TTL : 2 hours

? 特殊身份不敏感應用(如今日頭條、抖音)

Access token TTL = 1 hour

Refresh token TTL = 2 years

Balance是程序員世界很有趣的話題。

四、簽名 & 驗簽 演算法

RSA or HMAC or others?

主要從兩個維度考慮問題:

1. 安全

2. 性能

RSA 演算法的安全基於大數因式分解,而大數因式分解無特效公式,因此RSA只要密鑰/公鑰對足夠大,就足夠安全。我在我本機做了一些性能測試, 將簽名內容SHA256之後用RSA演算法簽名驗簽時間如下:

* 4096位RSA私鑰公鑰對 簽名 --> 每個49.36ms, 驗簽 --> 每個 0.6667ms

* 2048位RSA私鑰公鑰對 簽名 --> 每個6.43ms, 驗簽 --> 每個 0.1844ms

* 1024位RSA私鑰公鑰對 簽名 --> 每個1.088ms, 驗簽 --> 每個 0.0548ms

RSA 私鑰和公鑰不一樣,在token做authentication的case中,簽名使用私鑰,驗簽使用公鑰。

在內網,可以僅將公鑰交給非簽發籤名的系統來驗簽(防止其他系統泄露私鑰), 而私鑰僅由簽發籤名的系統保管。

HMAC 只有密鑰,簽名驗簽很快, 客戶端知道密鑰,易泄露。

不論用哪種演算法,都不需要將公鑰或私鑰交給前端。

五、總結

? Token放進cookie, Cookie 應該 setSecure = true , httpOnly, .domain.com, setMaxAge(-1)

? Access Token + Refresh Token的方式 是一個非常好的scaling 策略

? 每一次使用refresh token(如 獲取新access token、refreshtoken) 都需要訪問伺服器詢問其狀態

六.其他風險

? 簽名密鑰泄露

? 密鑰被破解

簽名密鑰泄露之後,理論上得到密鑰的人可製造任意被伺服器相信的內容。需要系統擁有隨時更換密鑰的能力、周期性的更換密鑰。

七、Reference Links:

? 流程圖地址:

https://www.processon.com/view/link/5ae9249de4b09b1bf6369cba

? 滴滴passport經驗:

http://www.hello-code.com/blog/architecture/201607/6099.html

? 講真別再用JWT了!

https://www.jianshu.com/p/af8360b83a9f

? OWASP:

https://www.owasp.org/index.php/JSON_Web_Token_(JWT)_Cheat_Sheet_for_Java#Token_weak_secret

? Building Secure User interfaces With JWTs(JSON Web Tokens) :

https://www.slideshare.net/stormpath/building-secure-user-interfaces-with-jwts

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 點融黑幫 的精彩文章:

代理協議Proxy protocol
令人窒息的擼貓操作之崽崽篇

TAG:點融黑幫 |