Session 和 JWT 可以說是現今主流的兩種登入認證機制,這篇文章會分別介紹 Session 和 JWT 的運作原理,並且比較他們之間的差別。
在開始比較 Session 和 JWT 的差別之前,首先我們要先來介紹一下什麼是 Session 身份認證機制。
所謂的 Session 認證,就是「將登入的資訊儲存在後端 Server 上」的一項技術,所以換句話說的話,就是後端 Server 會儲存這個使用者的登入資訊,並且回傳一個 Session id 給使用者。
舉例來說,假設我是一個使用者,我的帳號密碼是 Judy / 123,這時候當我在網站上輸入帳號密碼,並且嘗試登入時,首先後端 Server 會先去驗證我的帳號密碼 Judy / 123 是否曾經註冊過(畢竟得先註冊過才能登入),假設這組帳號密碼存在的話,後端 Server 就會生成一個 Session id(也就是 66EE89C175E
),並且將 Session id 存放在資料庫中,然後將 Session id 回傳給前端。
所以當前端(此處以瀏覽器為例)收到 Session id 的值時,前端就可以將這個 Session id 的值存放在 Cookie 中,等待後續使用。因此到這裡就完成了登入的操作,所以使用者理論上就會被跳轉回首頁,並且已經是成功登入的狀態。
而當使用者成功登入之後,假設使用者後續想要去 call 其他受保護的 api(ex:查看個人設定),這時候前端就可以在 call api 時,同時也帶上當初後端 Server 發放的 Session id,這樣後端在收到這一次的請求時,就可以去資料庫查詢一下這個 Session id 的值是否存在,如果存在的話,就表示這個使用者已經有成功登入過了,所以就可以允許這一次的 api 通過,進而返回實際的結果給前端。
所以對於 Session 這種登入機制而言,所有的登入記錄都是儲存在「後端 Server」上,前端所拿到的 Session id 的值,其實就只是一組沒有意義的亂碼,只有後端 Server 才知道這組 Session id 實際上對應到的是哪個使用者的登入資訊。
因此 Session 這種登入機制,他就是「將登入的資訊儲存在後端 Server 上」的一項技術。
了解了什麼是 Session 的登入機制之後,接著我們可以來介紹什麼是 JWT 的登入機制。
所謂的 JWT 認證,就是「將登入的資訊儲存在前端 Client 中」的一項技術,所以換句話說的話,就是會將使用者的登入資訊,直接儲存在前端的 Client 中,因此在後端 Server 中是不會儲存任何一筆登入資訊的!
這聽起來可能有點神奇,不過 JWT 的運作邏輯是這樣子的:
和前面一樣的例子,假設我是一個使用者,我的帳號密碼是 Judy / 123,這時候當我在網站上輸入帳號密碼,並且嘗試登入時,首先後端 Server 一樣是會先去驗證我的帳號密碼 Judy / 123 是否曾經註冊過。
但是這裡重點來了!!假設這組帳號密碼存在的話,後端 Server 就會生成一個 JWT 格式的 Token,並且會直接返回該 Token,而且「不需要」在後端 Server 中儲存這個 Token 的數據。
所以在 JWT 認證的世界中,後端 Server 是不需要儲存任何一筆 JWT 的數據的!!!後端 Server 要做的事情,就是生成 JWT Token,然後直接回傳就好,就是這麼簡單暴力!!!
這時候你可能會想:這樣到時候要怎麼驗證這個 JWT Token 是有效的?這時候就是展現 JWT 的神奇地方之處了!!
當使用者成功登入之後,假設使用者後續要想去 call 其他受保護的 api,這時候前端就可以在 call api 時,同時也帶上當初後端 Server 發放的 JWT Token,而當後端收到這個 Token 時,只要這個 JWT 的簽名驗證成功,後端就會無條件相信 JWT Token 中的內容,也就是 JWT Token 聲稱這個使用者的名字叫做 Judy,那後端就無條件相信這一次來請求的人就叫 Judy;JWT Token 聲稱這個使用者的 id 是 111,後端就無條件相信這個使用者的 id 是 111。
所以在 JWT 認證的世界中,後端就是這麼的天真可愛,只要 JWT 說什麼,後端就無條件相信他,完全不需要質疑 JWT 的安全性,因此在 JWT 的認證機制中,所有的登入記錄都是儲存在「前端 Client」上,前端所拿到的 JWT Token,就是一個包含所有使用者資訊的 Token,因此只要能夠正確解讀這個 JWT Token,就可以拿到使用者的所有資訊。
所以 JWT 這種登入機制,他就是「將登入的資訊儲存在前端 Client 上」的一項技術。
第一次接觸 JWT 的人,一定會很疑惑覺得:「到底為什麼後端可以這麼無條件的相信 JWT?」,事實上後端之所以可以無條件相信 JWT 中的內容,是因為 JWT 本身是一個帶有數位簽名的 Token 格式。
在 JWT 的組成結構中,可以分成 3 個部分,分別是:header
、payload
、signature
。
舉例來說,下面這一串亂碼:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoi5Y-k5Y-kIiwiaWF0IjoxNzIxMDAxNjAwfQ.G41XQGNNJ5Tp88U48aXh4n0XtGkpPkQ3xK6j43_61gE309hzyTVyciG5v05aVIvvY9NrApYiQdvwlMMrjRPFVV8xunghtKKFMj3kPx93Ll8Pf6n-tDiL_NZYqcusrgwtb-EDza80hMG5PTu75ogTIfRKr4jC0_FZzLaMix07LaZReoUSionTWTxJlm8qJc0BAFXgsaGNs9oVhCXOg_jJmOfFZBP0tD3q4xaKp9MTtLRTtslAhoAjPczdnPqaWGcaS8OY11RUTvvxijA7W-mPRlmqt0Hd_XForETUFZRdCKsPQIiGjkavycPtdiViVihQKstHlT4afEzYvzWSeK1cnw
就可以被解析成 header、payload、signature 這三個部分(每一個部分之間用一個點 .
隔開)。
header:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
payload:
eyJzdWIiOiIxMjMiLCJuYW1lIjoi5Y-k5Y-kIiwiaWF0IjoxNzIxMDAxNjAwfQ
signature:
G41XQGNNJ5Tp88U48aXh4n0XtGkpPkQ3xK6j43_61gE309hzyTVyciG5v05aVIvvY9NrApYiQdvwlMMrjRPFVV8xunghtKKFMj3kPx93Ll8Pf6n-tDiL_NZYqcusrgwtb-EDza80hMG5PTu75ogTIfRKr4jC0_FZzLaMix07LaZReoUSionTWTxJlm8qJc0BAFXgsaGNs9oVhCXOg_jJmOfFZBP0tD3q4xaKp9MTtLRTtslAhoAjPczdnPqaWGcaS8OY11RUTvvxijA7W-mPRlmqt0Hd_XForETUFZRdCKsPQIiGjkavycPtdiViVihQKstHlT4afEzYvzWSeK1cnw
而當後端在生成一個 JWT 的 Token 時,後端會先將 header
和 payload
的值組合起來,然後用 「hash + 非對稱加密」 的方式,生成一個 signature
(簽名)的值出來。
所以假設駭客偷偷修改了 payload
中的數據,這樣子最終解析出來的 signature 的簽名,就會和原始的簽名值不一樣,因此就可以透過這種 「數位簽名」 的方式,避免被駭客偷偷修改 payload
中的數據了。
補充:如果覺得上面這段太難的話,建議也可以先跳過 JWT 的詳細內容,只要先知道 JWT 是真的很強,後端可以直接無條件相信他就對了👍。
所以先總結一下上面的介紹的話:
因為 Session 的特性是將登入的資訊儲存在後端 Server 上,因此後端 Server 能夠主動刪除使用者的登入資訊(後端只要將資料庫中的 Session id 的數據刪除,該名使用者的登入記錄就會被刪除,因此就能夠實作「將使用者強制登出」的情境)。
但也因為 Session 的數據是儲存在資料庫中,因此當數量變多時,就會影響資料庫效能,所以當使用者數量到達百萬級之後,Session 認證就會遇到許多擴展上的困難。
因為 JWT 的特性是將登入的資訊儲存在前端 Client 中,所以就算使用者數量到達百萬級別,也不會對後端 Server 造成影響,因此很適合用在大型的微服務架構下、或是 SSO(Single Sign-On,單一登入)的使用情境。
但也因為 JWT 是將登入的資訊儲存在前端 Client 中,因此後端 Server「沒有能力」主動刪除使用者的登入資訊(因為後端會無條件相信 JWT Token 中的數據,所以後端沒有辦法主動撤銷某個 JWT Token,只能被動的等待該 JWT 自己過期失效)。
所以如果在使用 JWT 的前提下,仍舊想要實作「黑名單」之類的功能的話,就會需要走 Session 的回頭路,使用資料庫來記錄黑名單的使用者有哪些,就會喪失 JWT 本身的優勢。
綜觀以上的優缺點比較,其實 Session 和 JWT 真的沒有誰比較好、誰比較壞,他們兩個就像是站在對立面的選擇一樣,Session 的優點就是 JWT 的缺點、Session 的缺點就是 JWT 的優點,一切都要因實際的需求,選擇當下最適合的做法。
簡單一句話總結的話,就是 Session 和 JWT 的戰爭還未停止😂,甚至有時候也會看到混用他們的情況出現,因此建議大家兩種用法都要會,這樣在面對變動的需求時,才能選擇最適合的方式來解決問題!
補充:本文是擷取自 Hahow 線上課程 「資安一把罩!Spring Security 零基礎入門」 的內容,如果大家想了解更多的資安內容、以及如何應用 Spring Security,歡迎參考課程簡介。
這篇文章我們介紹了 Session 和 JWT 認證的差別,並且也比較了一下他們的優缺點,在現今 JWT 使用非常廣泛的時代中,多了解一點資安的技術也是絕對不會虧的!
如果你對後端技術有興趣的話,也歡迎免費訂閱 《古古的後端筆記》電子報 ,每週二為你送上一篇後端技術分享,那我們就下一篇文章見啦!