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