常規(guī)用戶認證需求
用戶先通過賬號密碼登錄獲取授權(quán)后,再獲取用戶詳情信息
對比傳統(tǒng)Session和JWT實現(xiàn)該需求的差異
傳統(tǒng)Session
流程:
- 客戶端使用賬號密碼來請求服務(wù)端
- 服務(wù)端對賬號密碼進行校驗
- 服務(wù)端創(chuàng)建一個Session姓迅,并將用戶登錄狀態(tài)端铛、用戶id钞支、有效時間等寫到session中
- 服務(wù)端將session保存到內(nèi)存中
- 服務(wù)端將session同步給其他集群節(jié)點
- 客戶端每次請求會帶上sessionId谆级,服務(wù)端根據(jù)sessionId找到對應(yīng)session棚壁,判斷session是否處于登錄狀態(tài)并取出用戶id
- 從session中獲取用戶id饺蔑,再根據(jù)用戶id到數(shù)據(jù)獲取用戶信息
- 返回用戶信息
總結(jié):
- 通常session都是保存在內(nèi)存中,隨著認證用戶量的增長服務(wù)端的開銷會明顯增大令哟。
- 在分布式架構(gòu)中恼琼,用戶在節(jié)點_1登錄后需要將session信息同步給其他節(jié)點妨蛹,或者保證同一個用戶總是路由到同一個節(jié)點上,否則用戶登錄狀態(tài)會失效
JWT(JSON WEB TOKEN)
流程:
- 客戶端使用賬號密碼來請求服務(wù)端
- 服務(wù)端對賬號密碼進行校驗
- 服務(wù)端生成jwt信息晴竞,并將用戶id寫到j(luò)wt的payload中
- 服務(wù)端將jwt信息返回給客戶端
- 客戶端發(fā)送獲取用戶信息請求并在header中帶上jwt信息
- 服務(wù)端驗證jwt的有效性并從中取出用戶id蛙卤,再根據(jù)用戶id到數(shù)據(jù)從查詢用戶信息并返回給客戶端
總結(jié):
- 使用JWT,服務(wù)端不用在內(nèi)存中保存任何信息噩死,在分布式架構(gòu)中也不存在同步session的過程
JWT詳解
組成
JWT由三個部分組成分別是header颤难、payload、signature用.
連接已维,如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.d1bf66192c1bff9038bcd212ba05dfde55c40d4e2254dd99c9c7653dd27c39ba
header:
{
"typ": "JWT",
"alg": "HS256"
}
typ: 類型行嗤,alg: 加密算法
將上面的json內(nèi)容Base64之后就形成了JWT的第一部分eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
payload:
{
"id": 1,
"username": "admin"
}
這部分為用戶自定義內(nèi)容(不要存放敏感信息)
將上面的json內(nèi)容Base64之后就形成了JWT的第二部分eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9
signature:
第三部分為第一部分和第二部分的簽名
let headerBase64 = new Buffer(JSON.stringify(header)).toString('base64');
let payloadBase64 = new Buffer(JSON.stringify(payload)).toString('base64');
let sha256 = crypto.createHmac('sha256', 'your salt');
sha256.update(headerBase64 + '.' + payloadBase64);
let sign = sha256.digest('hex');
let finalJwtString = headerBase64 + '.' + payloadBase64 + '.' + sign;
最終形成:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.d1bf66192c1bff9038bcd212ba05dfde55c40d4e2254dd99c9c7653dd27c39ba
栗子
授權(quán)請求
curl --request POST http://www.video4.cn:3030/session -H "Content-Type:application/json" -d '{"username":"admin","password":"123"}'
返回:
{
"code": 0,
"msg": "ok",
"data": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.d1bf66192c1bff9038bcd212ba05dfde55c40d4e2254dd99c9c7653dd27c39ba"
}
獲取具體信息
curl --request GET http://www.video4.cn:3030/api/projects/2 -H "Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.d1bf66192c1bff9038bcd212ba05dfde55c40d4e2254dd99c9c7653dd27c39ba"
返回:
{
"code": 0,
"msg": "ok",
"user": {
"id": 1,
"username": "admin"
},
"data": {
"id": 2,
"name": "project two",
"price": 99.99
}
}
當您看到本文章時測試服務(wù)可能已失效,可以自行搭建測試服務(wù)垛耳。
測試Demo源碼
地址:
https://github.com/hellsam/JWT_Demo
說明:
該Demo是基于koa框架模擬實現(xiàn)了JWT的基礎(chǔ)功能栅屏,如需在項目中使用建議使用現(xiàn)成的第三方庫飘千,如:jsonwebtoken