JWT全名JSON Web Token,因符合RESTful API無狀態原則而誕生。
傳統我們通常會用cookie/session的方式來做身分認證,也就是user登入後,用session id當作一種token,來做身份認證。
然而用session這種方法server會有額外的儲存負擔,查詢也會需要時間,加上一般production server不會只有一台,如果用session的話會有server之間如何共享session的問題。(當然如果您的SLB是by ip分流那就另當別論了)另外,使用JWT不會有像cookie一樣可能有無法跨域傳送的問題,也不會有CSRF攻擊的問題,因為我們不會把JWT儲存在cookie,不會讓瀏覽器自動送出,通常是駭客會透過攔截封包來擷取JWT,只不過還是建議使用HTTPS傳輸比較安全。
JWT字串由header, payload, signature三個部分組成,各自編碼後,用.串接起來即成為JWT字串。
JWT => Header.Payload.Signature
Header:
組成如下,alg是token被加密的演算法,typ是指token的type。
{
"alg": "HS256",
"typ": "JWT"
}
把這個json做base64 encode即為Header。
Payload:
這邊是放聲明訊息的地方,有以下幾種定義:
1. 標準聲明(Registered claims)
JWT規定的標準聲明,只是建議可以放,沒有強制一定要放。
2. 私有聲明(Private claims)
可自行定義的聲明,通常會放user的不敏感資料。
3. 公有聲明(Public claims)
實務上不太會需要用到,有時間再來研究。
Payload組成範例:
{
"iss": "http://www.example.com",
"exp": 1525318201,
"data": {
"user_id": 1,
"user_name": "Vic"
}
}
其中iss = JWT簽發者, exp = JWT的過期時間,這兩個都是標準聲明。標準聲明還有很多定義,可自行查詢。
data的部分就是自定義的user資料。
把這個json做base64 encode即為Payload。
Signature:
Signature是這樣組成的:
HMAC-SHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
其中secret=金鑰,只有伺服器知道這組金鑰。
HS256 = HMAC-SHA256
將header和payload json data做base64UrlEncode編碼後,用.來串接成data string,再使用header中指定的hash演算法HS256來對data string使用金鑰進行加密,產生簽名(signature)。
根據本文提到的範例,最終產生的JWT token如下圖:
Header.Payload.Signature
紅.紫.藍

JWT驗證流程如下:
1. 在前端打後端登入api,且user確認登入成功後,server會回傳這組JWT Token給前端。
2. 前端收到JWT Token後,一般會將其儲存在local storage中。
3. 之後前端要存取後端API的時候,需在header帶上這組token:
Authorization: Bearer ${JWT token}
假設JWT token是abc即為: Authorization: Bearer abc
4. 後端收到token後會驗證token有效性,決定是否可以存取此api。
本筆記參考:
1. https://ithelp.ithome.com.tw/m/articles/10196759?fbclid=IwAR2xU_FU1ma4DZMeqd2SJzHvoGAfb7jMLwjjkVtqIYHoVy81SBdRn-81_Nk
2. https://kknews.cc/zh-tw/code/ry55lxx.html
3. https://medium.com/%E4%BC%81%E9%B5%9D%E4%B9%9F%E6%87%82%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/jwt-json-web-token-%E5%8E%9F%E7%90%86%E4%BB%8B%E7%B4%B9-74abfafad7ba
4. https://www.mdeditor.tw/pl/2dmW/zh-tw
5. https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-%E9%80%8F%E9%81%8E-jwt-%E5%AF%A6%E4%BD%9C%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6-2e64d72594f8
6. https://yami.io/jwt/