1.JWT構成
- 頭部(header)
- 有效載荷(Payload)
- 簽名(signature)
2.header(header是一段json,經過base64編碼變成一段字符串,編碼前后對比圖如圖所示:)
- typ:token的類型,這里固定為JWT
- alg:使用的hash算法,例如:HMAC SHA256或者RSA
3.payload
- 存儲需要傳遞的信息,如用戶ID、用戶名等
- 還包含元數據,如過期時間、發布人等
- 與header不同,payload可以加密
4.signature
- 對header和payload部分進行簽名
- 保證token在傳輸的過程中沒有被篡改或者損壞
5.JWT工作原理
客戶端通過請求將用戶名和密碼傳給服務端,服務端將用戶名和密碼進行核對,核對成功后將用戶id等其他信息作為jwt的有效載荷(payload)與頭部進行base64編碼形成jwt(字符串),后端將這段字符串作為登陸成功的返回結果返回給前端。前端將其保存在localstroage或sessionstroage里,退出登錄時,刪除JWT字符串就可以。
每次請求,前端都會把JWT作為authorization請求頭傳給后端,后端進行檢查。
6.簡單實現
安裝:npm i jsonwebtoken --save
在controllers中:
const jsonwebtoken = require('jsonwebtoken'); const User = require('../models/user');class UserCtl {async login(ctx) { ctx.verifyParams({ //驗證參數 name:{type:'string',required:true}, password:{type:'string',required:true}, }) //驗證用戶名或密碼是否正確 const user = await User.findOne(ctx.request.body); if(!user){ ctx.throw(401,"用戶名或密碼不正確") } const { _id, name} = ctx.request.body; const token = jsonwebtoken.sign({ _id, name}, secret,{expiresIn:'1d'});//生成token,expiresIn:過期時間(1天) ctx.body = {token}; } } module.exports = new UserCtl()
7.附贈一個小技巧哦:
當我們登錄完,后端傳給前端token,前端再請求其他接口時需要攜帶這個token,一般我們是放在請求頭里,這個在postman上請求接口時怎么操作呢?
方法一:我們直接在header中添加。注意:內容為“Bearer”+空格+token ,不要問為什么,如下圖:
方法二:簡單一點,我們選擇“Authorization“,type選擇“bearer token“,並填寫token,如下圖:
但這個樣子還是有一丟丟麻煩,因為token總是過期,過幾天我們又要手動更換,這時我們可以設置一個全局變量:
在登錄的接口中這樣設置一個全局變量,看不懂的可以參考右下角的例子,具體的我也還沒有研究:
然后剛剛引入token的地方,改成引入變量token就可以了