- 安裝JWT相關(guān)的包
npm install jsonwebtoken express-jwt
- jsonwebtoken用于生成JWT字符串
- express-jwt用于將JWT字符串解析還原成JSON對象
- 使用require()函數(shù),將兩個包導(dǎo)入
// 導(dǎo)入 jsonwebtoken 和express-jwt 兩個包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
- 定義secret密鑰(secret實(shí)質(zhì)上就是一條字符串)
當(dāng)生成jwt字符串的時候,需要使用secret密鑰對用戶的信息進(jìn)行加密,最終得到加密好的JWT字符串
當(dāng)把JWT字符串解析還原成JSON對象的時候,需要使用secret密鑰進(jìn)行解密
// 創(chuàng)建secret對象
const secretKey = 'tokenKey123 num.1 ^_^'
- 調(diào)用jsonwebtoken包提供的sign(用戶信息對象,secret密鑰,有效期對象)方法,將用戶的信息加密成JWT字符串,響應(yīng)給客戶端
// 編寫登陸接口
app.post('/api/login',(req,res)=>{
const userinfo = req.body
// 登陸成功 => 將用戶信息轉(zhuǎn)換成token,并設(shè)置有效期
const token = jwt.sign({username:userinfo.username},secretKey,{expiresIn:'30s'})
res.send({
staus:200,
msg:'登陸成功!',
token:token
})
})
- 將JWT字符串還原為JSON對象
客戶端每次在訪問那些有權(quán)限接口的時候,都需要主動通過請求頭的Authorization字段,將token字符串發(fā)送到服務(wù)器進(jìn)行身份認(rèn)證
此時,服務(wù)器可以通過express-jwt這個中間件,自動將客戶端發(fā)送過來的Token解析還原成JSON對象
// 注冊將JWT字符串解析還原成JSON對象的中間件
// .unless()指定不需要訪問權(quán)限的接口
app.use(expressJWT({ secret: secretKey,algorithms:["HS256"] }).unless({ path: [/^\/api\//] }))
- 使用req.user獲取用戶信息
- 當(dāng)express-jwt這個中間件配置成功后,即可在那些有權(quán)限的接口中,使用req.user對象,來訪問從jwt中解析出的信息
app.get('/admin/getinfo',(req,res)=>{
console.log(res);
res.send({
staus:200,
message:'獲取用戶信息成功!',
data:req.user
})
})
- 捕獲解析jwt失敗后產(chǎn)生的錯誤
當(dāng)使用express-jwt解析Token字符串時,如果客戶端發(fā)送過來的Token字符串過期或者不合法,會產(chǎn)生一個解析失敗的錯誤,影響項(xiàng)目的正常運(yùn)行
我們可以通過Express的錯誤中間件,捕獲這個錯誤并進(jìn)行相關(guān)處理
完整實(shí)例代碼
// 1.導(dǎo)入express模塊
const express = require('express')
// 2.創(chuàng)建express服務(wù)器的實(shí)例
const app = express()
// 3.導(dǎo)入 jsonwebtoken 和express-jwt 兩個包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
// 允許跨域資源訪問
const cors = require('cors')
app.use(cors()) //將cors注冊到express對象中
// 解析post表單數(shù)據(jù)的中間件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
// 4.創(chuàng)建secret對象
const secretKey = 'tokenKey123 num.1 ^_^'
// 5.注冊將JWT字符串解析還原成JSON對象的中間件
// .unless()指定不需要訪問權(quán)限的接口
app.use(expressJWT({ secret: secretKey,algorithms:["HS256"] }).unless({ path: [/^\/api\//] }))
// 編寫登陸接口
app.post('/api/login', (req, res) => {
const userinfo = req.body
驗(yàn)證登陸
if (req.body.username !== 'admin' || req.body.password !== '000000') {
return res.send({ staus: 400, msg: '登陸失敗' })
}
// 登陸成功 => 將用戶信息轉(zhuǎn)換成token,并設(shè)置有效期
const token = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
res.send({
staus: 200,
msg: '登陸成功!',
token: token
})
})
app.get('/admin/getinfo',(req,res)=>{
console.log(res);
res.send({
staus:200,
message:'獲取用戶信息成功!',
data:req.user
})
})
// 編寫錯誤中間件,用于捕獲解析JWT失敗后產(chǎn)生的錯誤
app.use((err,req,res,next)=>{
// 這次失敗是由token解析失敗導(dǎo)致的
if(err.name==='UnauthorizedError'){
return res.send({
staus:401,
message:'無效的token'
})
}
res.send({
status:500,
message:'未知的錯誤'
})
})
// 對本地的86端口進(jìn)行監(jiān)聽
app.listen(86, () => {
console.log("Running at 127.0.0.1:86!")
})