在Express中使用JWT

  1. 安裝JWT相關(guān)的包
npm install jsonwebtoken express-jwt
  • jsonwebtoken用于生成JWT字符串
  • express-jwt用于將JWT字符串解析還原成JSON對象
  1. 使用require()函數(shù),將兩個包導(dǎo)入
// 導(dǎo)入 jsonwebtoken 和express-jwt 兩個包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
  1. 定義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 ^_^'
  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
    })
})
  1. 將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\//] }))
  1. 使用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
    })
})
  1. 捕獲解析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!")
})
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容