1. 程式人生 > >SpringBoot系列: Web應用鑑權1

SpringBoot系列: Web應用鑑權1

==============================
web 專案鑑權
==============================
主要的鑑權方式有:
1. 使用者名稱/密碼鑑權, 然後通過 Session/Cookie 儲存鑑權結果.
2. 使用者名稱/密碼鑑權, 然後通過 JWT 儲存鑑權結果.

JWT 的優點:
1. Jwt 是一個 stateless 方案, 不需要解決 session 共享問題.
2. Jwt 更適合於手機端的訪問, 因為移動端不支援 cookie.
3. Jwt 更適合於微服務端的驗證, 因為微服務的使用方通常不是web browser, 而是服務端程式, 使用 jwt 更方便.
3. Jwt 支援跨域訪問, 而 Cookie不允許.
4. Jwt 因為不依賴cookie, 所以不需要考慮CSRF(跨站請求偽造)攻擊.
JWT 的缺點:
1. 伺服器端不能主動登出 Jwt token, 使用 Session 方式時, 伺服器端是能主動 logout 一個登陸.
2. 對於普通 Web 瀏覽器, 使用 cookie/Session 幾乎無感, 而 jwt 需要在請求的時候加 header.


==============================
企業內專案鑑權的推薦
==============================
Web UI 專案, 採用 Session 來做許可權驗證, Web UI 專案關注的是使用者級的許可權.
API 服務專案, 採用 access token 做許可權驗證, 關注的是來源 app 是否有許可權(粗粒度許可權管控), 並不是每個登陸使用者的許可權. 

 

----------------------------
App Authentication 伺服器
----------------------------
專門建有統一的 App Authentication 伺服器, 集中管理 Access token 簽發, 可以將企業中的所有"微服務"都納入其管理, 統一管理, 有利用服務的治理.


----------------------------
Access token 的申請
----------------------------
一個 WebUI 應用或微服務如要訪問其他微服務, 需要向統一的 App Authentication 伺服器申請 Access Token, 申請時提供自己的 appId/appSecret 和目標微服務 appId, 由 App Authentication 伺服器負責決定是否簽發 access token, 在 token 中記錄申請 appId/目標 appId, 以及賦予的角色.

為了防止 appId 被冒用, 需要提早將 appId 和它所在的伺服器 IP 加到 App Authentication 的白名單中.

為了防止 access token 被大量擴散, 針對同一個 appId 和目標 appId, 同時只能有兩個 Access Token, 之所以是兩個, 一方面可有效限制了 token 的數量, 另外能無縫覆蓋 token 失效期.

為了防止重複攻擊, 需要設定token有效期, 企業內部也不宜太短, 設定1~2天較好一些.

一個應用申請到 Access token 之後, 有責任先將該 token 儲存, 最好儲存到 DB 中, 另外最好有一個定時任務定期申請 access token, 並在 DB 中維護一個 token 池, 在用的時候應使用有效期更遠的那個 token.

----------------------------
Access token 的使用
----------------------------
在每次訪問微服務的時候, 都要在 headers 上加上 token 資訊, 加到 X-Auth-Token 上.
在受訪微服務中, 驗證 access token 是否有效, 是否已經過期, 並提取出來源 app 的角色, 然後進行下一步許可權上的管控.


==============================
術語解釋
==============================
JWT: 全稱 json web token, 包含 header 和 claims 和 signature 三個部分. 
   因為 token 中已經帶有 signature, 所以具有 token 自驗證機制, 能防止偽造.
   在 claim 中可以設定一個過期時間, 所以能防止 token 被人長期冒用.

Access token(基於 jwt):
   Access token: 對於開放平臺, 一般通過 appId/appSecret 來獲取一個 access token, 比如微信就是這樣, 該 access token 有效期為 2 個小時, 呼叫微信公眾號的所有介面都需要帶上 access token.
在微信平臺中, 重複獲取 Access token, 將導致之前獲取的 Access token 失效. 個人認為: 要在伺服器端主動失效已經簽發的 token, 這將又走到了 session 的路子上, 這是一個 1+1<1 的做法, 也許只要控制每個 appId 同時能申請幾個 Access token 就行了, 比如限制 2 個有效 Access token.

 

Refresh token(基於 jwt)
微信是通過 appId/appSecret 來獲取 Refresh token, 有些平臺是通過 Refresh token 來獲取 Access token, 所以 Refresh token 有效期比較長. 個人認為, 微信的做法更好一些, 一般情況下沒有必要再引入 Refresh token 這個概念.


==============================
參考
==============================
基於Token的WEB後臺認證機制
http://www.cnblogs.com/xiekeli/p/5607107.html
使用JSON Web Token設計單點登入系統
https://leon_lizi.gitbooks.io/json-web-token/content/chapter2.html#
聊一聊JWT與session
https://juejin.im/post/5a437441f265da43294e54c3
重拾後端之Spring Boot(四):使用JWT和Spring Security保護REST API
https://juejin.im/post/58c29e0b1b69e6006bce02f4