JWT的工作原理

本地文件

image-20220717163156633

JWT的组成部分

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

三者之间使用英文的.分隔,格式如:Header.Payload.Signature

下面是JWT字符串的示例:

JWT字符串示例
1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JWT的三个部分各自代表的含义

Payload部分是真正用户信息,它是用户信息经过加密之后生成的字符串。

HeaderSignature是安全性相关的部分,只是为了保证Token的安全性。

JWT的使用方式

客户端收到服务器返回的JWT之后,通常会将它储存在localStoragesessionStorage中。
此后,客户端每次与服务器通信,都要带上这个JWT的字符串,从而进行身份认证。推荐的做法是把JWT放在HTTP请求头的Authorization字段中,格式如下:

1
Authorization:Bearer <token>

安装JWT相关的包

安装一下两个相关的包:

1
npm install jsonwebtoken express-jwt

其中:

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

导入JWT相关的包

1
2
3
// 导入JWT相关的包 jsonwebtoken express-jwt
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')

定义secret密钥

1
2
// 定义secret 密钥 建议将密钥命名为 secretKey
const secretKey = 'xiaobaitest'

将JWT字符串还原为 JSON对象

注意:只要配置成功了 express-jwt中间件,就可以把解析出来的用户信息挂载到req.user属性上

客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的Authorization字段,将Token字符串发送到服务器进行身份认证。
此时,服务器可以通过``express-jwt这个中间件,自动将客户端发送过来的Token解析还原成JOSN`对像:

1
2
3
4
// 一定要在路由之前配置解析 token 的中间件 
const expressJWT = require('express-jwt')
// 注册将 JWT 字符串解析还原成JSON对象的中间件
app.use(expressJWT({secret : secretKey}).unless({path :[/^\/api\//]}))

使用req.user获取用户信息

express-jwt这个中间件配置成功之后,即可在那些有权限的接口中,使用req.user对象,来访问从JWT字符串中解析出来的用户信息了,示例代码如下:

app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 登录用户的函数
exports.login = (req, res) => {
const userinfo = req.body
const usernameSql ='select * from ev_users where username= ?'

db.query(usernameSql,userinfo.username,(err,results)=>{
// 错误提示
if (err) return res.cc(err)

if (results.length !== 1) return res.cc('登录失败')

// 验证密码是否正确
const comparreResults = bcrypt.compareSync(userinfo.password,results[0].password)
if (!comparreResults) return res.cc('密码错误!请重新输入')

// 在服务端生成token字符串
const user = {...results[0],password:'',usre_pic:''}
// 对用户的信息进行加密,生成token字符串
// console.log(config.expriresIn)
const tokenStr = jwt.sign(user,config.jwtSecretKey,{expiresIn: '48h'})
res.send({
status:0,
msg:'登录成功',
token:'Bearer '+tokenStr,
})
})
}