事情是這樣的:我們做了一個小程式,在與後端 Api 互動的過程中總要帶上個
token
。然而這個token
過了兩小時就失效,so 我們雖然做了處理了失效的邏輯,但是怎麼模擬失效的token
呢,這一切都要從JWT說起...
定義
JWT,JSON Web Token。一般用於 OAuth 2.0 鑑權系統中,由三部分組成,用 .
拼接:
header
定義 jwt 以及演算法型別payload
真正傳送的資料signature
由 header 與 payload 用演算法生成的簽名
你看到的一個jwt
可能是這樣的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTM1MDQzNTc5MTgsInVzZXIiOiJ0YW8iLCJzZXgiOjB9.Rg6jvDV2EMqtPQc2d4krpAUYC-hMtc54vSsZAuCxuKQ
header
格式:
{
"typ": "JWT",
"alg": "HS256"
}
複製程式碼
type 固定為JWT
;algorithm 表示使用的演算法,常用的有HS256
(sha-256)、RS256
(rsa-256)等等
payload
(無格式,推薦 json 形式)
{
"exp": 1553504357918,
"user": "tao"
}
複製程式碼
expire 指明瞭此 token 的有效時間,除此之外 RFC 還規範了其它幾個欄位比如說iss
(issuer 生成者)、iat
(issued at 生成時間)、jti
(JWT ID 唯一標識)
signature
生成方式: 將header
與payload
編碼成 base64,再用.
拼接成一個字串,最後通過 Hmac(hash-based message authentication code) 演算法生成
hmac 與雜湊演算法的區別就是多了個 secret key,所以它也叫 keyed-hasing
注意:payload 中不應該放入敏感資料,諸如使用者密碼之類。因為它能直接被解碼
簡單的例子
const crypto = require('crypto');
// 固定格式
const header = {
typ: 'JWT',
alg: 'HS256',
};
// 需要傳輸的資料,也可以是一段字串
const payload = {
exp: 1553504357918,
user: tao
};
const arr = [];
// 簽名所用祕鑰
const secret = 'Zeus';
// 編碼 header 與 payload
arr.push(Buffer.from(JSON.stringify(header)).toString('base64'));
arr.push(Buffer.from(JSON.stringify(payload)).toString('base64'));
// 用 . 拼接,得到:
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NTM1MDQzNTc5MTgsInVzZXIiOiJ0YW8ifQ
const encodeStr = arr.join('.');
// 生成 signature
const signature = crypto
.createHmac('sha256', secret)
.update(encodeStr)
.digest('base64');
arr.push(signature);
// 最後生成的 JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTM1MDQzNTc5MTgsInVzZXIiOiJ0YW8iLCJzZXgiOjB9.Rg6jvDV2EMqtPQc2d4krpAUYC-hMtc54vSsZAuCxuKQ
arr.join('.');
複製程式碼
目前 OAuth 2.0 以 JWT 形式生成的 token 比較主流,可以瞭解一下~