Skip to content

十五、在Express中使用JWT

1、JWT的介绍

1、什么是JWT

JWT是目前最流行的跨域解决方案

2、JWT的工作原理

用户的信息通过Token字符串的形式,保存在客户端的浏览器中。服务器通过还原Token字符串的形式来认证用户的身份

3、JWT的组成部分

JWT通常由三部分组成,分别是Header(头部)、Payload(有效荷载)、Signature(签名)

三者之间用英文“.”分隔,格式为

bash
Header.Payload.Signature

注意:

  • Payload部分才是真正的用户信息,他是用户信息经过加密之后生成的字符串
  • Header和Signature是安全性相关性的部分,只是为了保证Token的安全性

4、JWT的使用方式

客户端收到服务器返回的JWT之后,通常会将它存储在localStorage或sessionStorage中

此后,客户端每次与服务器通信,都要带上这个JWT的字符串,从而进行身份认证。推荐的做法是把JWT放在HTTP请求头的Authorization字段中

Authorization:Bearer <token>

2、在express中使用JWT

1、安装JWT相关的包

bash
npm install jsonwebtoken express-jwt

其中:

  • jsonwebtoken用于生成JWT字符串
  • express-jwt用于将JWT字符串解析还原成JSON对象

2、导入JWT相关的包

js
//1、导入用于生成JWT字符串的包
const jwt=require('jsonwebtoken')
//2、导入用于将客户端发送过来的JWT字符串,解析还原成JSON对象的包
const {expressjwt:expressJWT}=require('express-jwt')

3、定义secret密钥

为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,我们需要专门定义一个用于加密和解密的secret密钥

  • 当生成JWT字符串的时候,需要使用secret密钥对用户的信息进行加密,最终得到加密好的JWT字符串

  • 当把JWT字符串解析还原JSON对象的时候,需要使用secret密钥进行解密

js
  const secretKey="hello world"

4、在登录成功后生成JWT字符串

调用jsonwebtoken包提供的sign()方法,将用户的信息加密成JWT字符串,响应给客户端

js
app.post('/api/login',(req,res)=>{
	res.send({
		status:200,
		message:"登录成功",
		//调用jwt.sign()生成JWT字符串,三个参数分别是用户信息对象、加密密钥、配置对象
		token:jwt.sign({
			username:userinfo.username
		},secretKey,{expiresIn:'30s'})
	})
})

5、测试

js
// 导入express
const express = require('express')
// 创建服务器
const app=express()

const jwt=require('jsonwebtoken')
const {expressjwt:expressJWT}= require('express-jwt')

// 允许跨域
const cors=require('cors')
app.use(cors())

// 解析post表单数据的中间件     
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended:false}))

// 定义密钥,建议密钥命名为secretKey
const secretKey="huangdaquan"
app.use(expressJWT({secret:secretKey,algorithms:["HS256"]}).unless({
    path:[/^\/api\//]
}))

//登录接口
app.post('/api/login',(req,res)=>{
    const userinfo=req.body
    //登录失败
    if(userinfo.username!=='admin'||userinfo.password!=='000000'){
        return res.send({
            status:400,
            message:"登陆失败!"
        })
    }
    // 登录成功
    // 传递用户信息,生成token
    const tokenStr=jwt.sign({
        username:userinfo.username,
        password:userinfo.password
    },secretKey,{
        expiresIn:'30s'
    })

    res.send({
        status:200,
        message:'登录成功!',
        token:tokenStr
    })
})

// 获取用户信息
app.get('/admin/getinfo',(req,res)=>{
    // 中间件解析出来的用户信息,挂载到req.auth上面
    console.log(req.auth);
    res.send({
        status:200,
        message:"获取用户信息成功!",
        data:req.auth
    })
})

// 处理错误的中间件放在路由后面
app.use((err,req,res,next)=>{
    if(err.name==="UnauthorizedError"){
        return res.send({
            status:401,
            message:"无效的token"
        })
    }
    res.send({
        status:500,
        message:"未知的错误"
    })
})

app.listen(8080,()=>{
    console.log("服务器启动了!");
})

依这段代码为准

postman测试:

登录:

  • post请求
  • x-www-form-urlencoded

获取用户信息:

  • get请求

  • headers添加Authorization,格式为

    Bearer 你的token值

6、捕获解析JWT失败后产生的错误

js
// 处理错误的中间件放在路由后面
app.use((err,req,res,next)=>{
    if(err.name==="UnauthorizedError"){
        return res.send({
            status:401,
            message:"无效的token"
        })
    }
    res.send({
        status:500,
        message:"未知的错误"
    })
})