之前常常聽到 jwt,但沒有很了解,就來研究一下吧
什麼是 JWT
- JWT 是基於 JSON 的開放標準 (RFC 7519)
- 一般被用來在 身份提供者 和 服務提供者 間傳遞被 認證 的用戶身份訊息,以便於從資源伺服器獲取資源
- 同時也可以增加一些額外的聲明訊息,該 token 也可直接被用於認證,也可被加密
- 特別適用於分佈式站點的單點登錄(SSO)場景
先來瞭解一般 session 和 jwt 的差別
Session
Http 協議本身是無狀態的,所以無法知道每個 request 來的是誰? 因此用戶每次 request 就必須提供帳號密碼,以便證明身份,但每次都要另外輸入帳號密碼,豈不是很麻煩?
所以當用戶第一次發 request 過來後,就會產生一組 token 紀錄在 db 和 session,並且將這組 token 給用戶,告訴其保存在 cookie,當下次發 request 的時候,就直接帶這組 token 以便證明身份。
JWT
JWT 的組成內容有三個部分,由 .
做區隔,最後透過這三個部分,串成一個 Jwt 字串
1. Header 頭部
1 2 3 4 |
|
進行 base64 加密(該加密是可以對稱解密的)
1
|
|
2. Payload 載荷
這裡放聲明內容,可以說就是存放溝通訊息的地方,在定義上有 3 種聲明 (Claims)
- Reserved (註冊聲明)
- Public (公開聲明)
- Private (私有聲明)
註冊聲明參數 (建議但不強制使用)
- iss (Issuer) - jwt簽發者
- sub (Subject) - jwt所面向的用戶
- aud (Audience) - 接收jwt的一方
- exp (Expiration Time) - jwt的過期時間,這個過期時間必須要大於簽發時間
- nbf (Not Before) - 定義在什麼時間之前,該jwt都是不可用的
- iat (Issued At) - jwt的簽發時間
- jti (JWT ID) - jwt的唯一身份標識,主要用來作為一次性token,從而迴避重放攻擊
1 2 3 4 5 |
|
進行 base64 加密(該加密是可以對稱解密的)
1
|
|
3. Signature
由三個部分組成
- header (base64後的)
- payload (base64後的)
- secret
1
|
|
secret 要保存在 server 端,jwt 的 簽發驗證都必須使用這個 secret,當其他人得知這個 secret,那就意味著客戶端是可以自我簽發 jwt ,因此在任何場景都不應該外流
進行 base64 加密
1
|
|
最後由三個部分由 .
組成
1
|
|
使用方法
在發 request 的時候在 header 加入 Authorization: Bearer <token>
1 2 3 4 5 |
|
優點
- 跨語言,因為 json 格式大部分語言都可使用
- 可儲存一些簡單但非敏感的商業邏輯 - role ..
- 構成內容簡單,佔用 Size 小方便傳輸
- 不需在 server 保存 session,所以它易於應用的擴展
安全相關 Security
- Base64 是可逆的加密方式,不適合存放敏感訊息,因為該部分是客戶端可解密的部分
- 用來加密的 Secret 要保護好,存在 server 端
- 使用 Https 協議 - 避免敏感訊息被嗅探
- 使用 HttpOnly 來防止 Cookie 被 JavaScript 讀取,從而避免跨站腳本攻擊(XSS攻擊)
JWT的適用場景
- 一次性驗證 ex: 信件中的連結
- restful api 的無狀態認證
- 單點登錄+會話管理(不推薦,絕大多數情況下,傳統的 cookie-session 機制工作得更好)
參考文件: