淺談 Session 與 JWT 差異
前言
在剛觸碰後端時,很常為了會員驗證的 Session 而苦惱不久對吧?前陣子我第一眼看到 JWT 的時候,一丟 Google 發現有人用 JWT 來代替 Session,繼續查下去又發現有人說不要這樣做,所以 JWT 到底是啥?可以用在哪?
目錄
- 認證與授權
1. 認證
2. 授權 - Session 是什麼
1. 小故事
2. 運作原理
3. 與 Cookie 差在哪? - JWT 又是什麼
1. Base64Url
2. head
3. payload
4. signature
5. 運作原理
6. 使用時機
認證與授權
在介紹 Session 與 JWT 前,我們要來談談這兩個單字。以辦信用卡來舉例,通常辦卡前銀行會確認你的收入是否穩定,再來決定是否發行信用卡給你,因此可以分為:
認證
讓銀行知道你的收入是否穩定。
授權
收入通過標準,銀行發行信用卡給你。
Session 是什麼
Session 基於 Cookie,指的是在網路上的「狀態」。被用在身份驗證上是較常見的。
小故事
不知道大家有沒有用 Booking.com 訂房過,他有個機制是你在兩年內訂房超過幾次就可以升級 Genius 會員,還分了很多階級有不同的優惠折扣。
所以當我輸入完帳密登入後,Booking 會先去查看是否有此人,通過了「認證」後,發現我在訂單記錄上超過兩次訂房,所以「授權」了我 Genius 1 級會員的優惠。
運作原理
當 Client 輸入帳密登入後,Server 會產生一筆 Session 記錄在伺服器,同時把你的身份特徵 SessionID 送回去 Client 端加密保存 ( 只有 Server 能解密查看 )。之後你在網頁上的操作,Server 只要依據你的 SessionID,就能查看剛剛在你身上存的 Session。
想要清除的話,除了等待 Session 過期,還可以使用網站常有的登出,其實就是由 Server 來幫你消除 Session,另外也可以從 Client 端來清除 Cookie ( SessionID )。
與 Cookie 差在哪?
雖然說是基於 Cookie,但不同的是 Session 主要還是存在 Server 端,只有單一個 SessionID 會被送去 Client 端並且加密。
JWT 是什麼?
原名 ( JSON Web Tokens ),基本上就是帶時效的 Token。
JWT 主要分為三段,個別為 header、payload 與 signature,中間以 . 做區隔,每一段都是透過 Base64Url 去編碼,中間的 payload 有時候會加密。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Imhpcm9AZ21haWwuY29tIn0.WAKjPd_0qcEG3dA9pEwAiw-0ADb8VwqFlSWiIYJTymo
Base64Url
與 BASE64 差在最後的 「 = 」 號會去掉,「 - ` /」符號會換成底線「 _ 」, 「+」會換成 dash「 - 」。
header
存放 token 型別與加密方式 。
{
"alg": "HS256", // 加密方式
"typ": "JWT" // token 型別
}
以 Base64Url 編碼後:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload
存放需要傳遞的訊息。因為只透過編碼轉換「未經過加密」,不建議在裡面放重要資訊。
另外官方有提供一些可以用的屬性大概分為:
- iss: 發行人
- exp: 到期日
- sub: 主題
- aud: 收件人
- nbf: 不接受早於…日期/時間
- iat: 發行時間
- jti: 唯一識別符,JWT 只能使用一次
接著我們來看看轉換結果:
{
"email": "hiro@gmail.com"
}
編碼後:
eyJlbWFpbCI6Imhpcm9AZ21haWwuY29tIn0
signature
最後的部分,有點像是我們平常買東西條碼上最後的檢查碼,首先會先取得 header 裡的加密方式 SHA256,再透過以下方式產生:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
secret 則是可以打上自己要打的,最後一樣會轉換成 Base64Url:
再把三段加在一起就算是 JWT 了!
WAKjPd_0qcEG3dA9pEwAiw-0ADb8VwqFlSWiIYJTymo
運作原理
關於 Auth 則是選擇 Bearer Token,另外也有放在 Body 裡或是 URL 後方的做法,但需要多注意一些細項,詳細可以參考 Bearer Token 的使用方法。
使用時機
看完上面可以知道,JWT 的主要目的只是「 確立資料來源以及可信度 」。因此在應用上也會限制較多。以下是較常被使用的時機:
- 跨伺服器下的請求
可以參考運作原理的圖,如果我們同時擁有許多伺服器,可以把身份驗證伺服器獨立出來,登入後使用 JWT 就可以在不同伺服器遊走。 - 一次性、時效短的請求
因為 JWT 不能主動撤銷,一般用於會員身份驗證會不太適合,多用於一次性下載檔案,或是時間限制內更改密碼等等… - APP 身份驗證
一般 APP 是不存在 Session 的,所以在持續身份驗證上可以使用 JWT,但要確保使用者的執行環境是安全的。
結論
常常看到有人會問說:
JWT 可以代替 Session 嗎?
這其實是個假議題,東西存在一定有它的價值。透過 Booking.com 的例子,我們可以得知 Session 能較方便的「授權」不同身份,以及能夠主動撤銷。反之 JWT 不能主動撤銷,出來的 Token 一大坨,除了傳輸上較慢,也需要花較多時間去解碼。
關於更深的資料可以參考:別再使用 JWT 作為 Session 系統!