原文參考:https://mp.weixin.qq.com/s/4ZgxcJn-kYCLjvA1foK_yQ
前后端分離常用的認證方式
前后端分離中前后端的交互是通過 API 進行的,那么其中的認證是少不了的。前后端分離中常用的認證方式有下面幾種:
- Session-Cookie
- Token 驗證
- OAuth(開放授權)
Session-Cookie 方式
Session-Cookie 方式是我們開發 web 應用時最常用的認證方式。它的認證過程一般是這樣的:

- 1/ 用戶瀏覽器向服務器發起認證請求,將用戶名和密碼發送給服務器。
- 2/ 服務器認證用戶名和密碼,若通過則創建一個 session 對話,並將用戶信息保存到 session 中。session 的信息可以是保存到服務器文件、共享外部存儲、數據庫等存儲中,等下次請求時查詢驗證使用。
- 3/ 服務器會將該 session 的唯一標識 ID,返回給用戶瀏覽器,並保存在 cookie 中。
- 4/ 用戶請求其他頁面時,瀏覽器會自動將用戶的 cookie 攜帶上,並發起接口請求,服務端收到請求后,從 cookie 解析出 sessionID, 根據這個 sessionID 查詢登錄后並保存好的 session,若有則說明用戶已登錄,放行。
該方式是 MVC 架構中最常用的認證方案,在前后端分離中也是可以用的。幾乎所有的 Web 框架都默認集成了 Session-Cookie 的認證方式,而且對 Session-Cookie 方式的安全性和穩定性方面都有很成熟的處理方案。
當前端代碼使用后端 web 框架當做 web 容器驅動時,Session-Cookie 方案可作為首選的認證方案。
Token 方式
Token 方式是不同系統交互、前后端架構常用的認證方式。Token 方式的認證流程如下:

- 1/ 用戶使用用戶名和密碼登錄,將用戶名和密碼發送給服務器。
- 2/ 服務器驗證用戶名和密碼,若正確,則簽發 token,返回給用戶。
- 3/ 用戶收到 token 后,將其存儲起來,web 服務一般為 localStrage 或 cookie。
- 4/ 用戶請求其他資源頁面時,會攜帶 token,一般放到 header 或參數中,發送給服務端。
- 5/ 服務器收到后,驗證 token,判斷用戶的正確性。
JWT(JSON Web Token)是最常用的一種 Token 認證方式,已成為 Token 認證的標准事實。JWT 方式將 Token 分段,使其可以保持少量數據,還增加了簽名驗證,確保了 token 的安全性。JWT 網上介紹的資料很多,這里不再贅述。不了解的,可參考下邊這些資料:
- JSON Web Token 入門教程[1]
- JWT 官網[2]
OAuth 方式
OAuth(Open Authorization)是一個開放標准,允許用戶授權第三方網站訪問他們存儲在服務端的用戶信息。我們常見的的 QQ、微信等第三方登錄便是 Auth 認證方式。OAuth 協議有 1.0 和 2.0 兩個版本。相比較 1.0 版,2.0 版整個授權驗證流程更簡單更安全,也是目前最主要的用戶身份驗證和授權方式。
OAuth 更像是一種授權機制。數據的所有者告訴系統,同意授權第三方應用進入系統,獲取這些數據。系統從而產生一個短期的進入令牌(token),用來代替密碼,供第三方應用使用。
在單純的前后端分離系統中,OAuth 並不是常用的方式,它更多的應用在不同系統之間的授權交互。
對比思考
刨去不常用的 OAuth,這里對比兩種前兩種常用的認證方式 JWT Auth 和 Session-Cookie Auth ,到底誰才是前后端分離認證的最佳實踐呢。從下面幾個方向分析比對。
可擴展性
Session-Cookie 是有狀態的服務,在服務端保存了 session 的信息。當服務端擴容的時候,需要考慮到 session 的共享問題,這個問題已有成熟的解決方案,可使用 session 復制、共享、持久化等方式解決,大多數的分布式 Web 框架已經集成了處理方案。JWT 驗證方式是無狀態的服務,服務端可隨意擴縮容。
Session-Cookie 方式基於 Cookie,也就是必須是瀏覽器或支持 Cookie 的瀏覽器封裝的框架,純移動端無法使用。JWT 不同,不依賴 Cookie, 只要在本地可存儲即可。
安全性
Web 開發中常見的兩個安全問題 XSS(跨站點腳本攻擊) 和 CRSF (跨站點請求偽造)。前者利用注入腳本到用戶認證網站上,執行惡意腳本代碼。后者則利用瀏覽器訪問后端自動攜帶 cookie 的機制,來跨站偽造請求。XSS 只要我們對注入端,進行過濾、轉義就能解決,CRSF 是我們重點關注的。
在 Session-Cookie 認證方式中,因為把 SessionID 保存在了 Cookie 中,很容易引起 CRSF 攻擊。在大多數的 WEB 框架中有集成解決方案,如 Django 的 csrftoken 、Beego 的 xsrfToken 等。在使用 Session-Cookie 方案時建議開啟 web 框架的 csrf 功能。
JWT 認證,可以把 Token 存放在 Cookie 或 localstorage。建議存在 localstorage,這樣就徹底避免了 CRSF 攻擊。
另外 JWT 有幾個安全性的問題,需要注意:
- 1/ JWT 是明文編碼 JWT 的編碼是明文 Base64 的一個編碼,是可以反編譯的。在使用 JWT 傳輸信息的時候,不要放置重要敏感信息,最好使用 https。
- 2/ JWT 泄露問題 解決 JWT 的泄露問題是一個平衡的問題。有三種處理方式由輕到重,看你業務重要性酌情選擇:
- 將 JWT 的過期時間設置的很短,即使泄露也無關緊要。
- 在服務端設計 JWT 的黑名單機制,將泄露的 Token 加黑名單即可。
- 保存簽發的 JWT,當 JWT 泄露時,直接設置失效。
性能
Session-Cookie 方案,因為后端服務存儲了 Session 信息,在認證的時候需要查詢,當有大量認證的時候是非常耗費資源的。JWT 可以把信息放到 token 中,只需要驗證解碼,使用簽名驗證 token 即可,相對來說效率會有提升。
從上面三個方面,我們分析了 Session-Cookie 和 JWT 方式各自的優缺點,和面對問題的一些應對方案。相信大家會有自己的心里選擇。
拋開業務場景談技術都是耍流氓。不同的業務場景,不同的架構設計,適用的認證方式也是不同的。這里按我自己的經驗總結了下,什么情況下該使用那種認證方式,大家可參考。
適用 Session-Cookie 認證方案的情況:
- 項目只有 web 端的情況;
- 項目人員配置少,且前后端開發都會參與;
- 項目前后端分離不徹底,前端使用后端 web 框架作為服務容器啟動;
使用 JWT 認證方案的情況:
- 項目人員配置充足,分工明確;
- 項目除 web 端外還有移動端;
- 臨時的授權需求;
- 純后端系統之間的交互。
本文圍繞前后端分離這個話題總結分享了前后端分離時的認證方案。這些僅僅是通用的一般方案,在具體的業務場景中,還有很多不典型的擴展的驗證方案也是極好的,歡迎大家留言討論自己心中的最佳認證方案。
參考及擴展閱讀
- 傻傻分不清之 Cookie、Session、Token、JWT[3]
- 四種認證方式[4]
- JWT 簡介[5]
- JWT 勿用[6]
- (譯)別再使用 JWT 作為 Session 系統!問題重重且很危險。[7]
- OAuth 2.0 的一個簡單解釋[8]
- OAuth 2.0 的四種方式[9]
