前后端的身份认证:JWT认证机制

1,964 阅读4分钟

JWT认证机制

什么是JWT

JSON Web Token,是目前最流行跨域认证解决方案

JWT的工作原理

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

JWT的组成部分

JWT通常由三部分组成,分别是Header(头部),Payload(有效载荷),Signature(签名)。 三者之间使用英文的“.”分隔,格式如下

    Header.Payload.Signature

image.png

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

JWT的使用方式

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

 Authorization:Bearer <token>
  1. 安装JWT相关的包 运行如下命令,安装如下两个JWT相关的包:
npm install jsonwebtoken express-jwt

其中:

  • jsonwebtoken 用于生成JWT字符串
  • express-jwt 用于将JWT字符串解析还原成json对象
  1. 导入JWT相关的包
//导入express模块
const express = require('express')
//创建express的服务器实例
const app = express()
//安装并导入JWT相关的两个包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')

//允许跨域资源共享
const cors = require('cors')
app.use('cors()')
  1. 定义secret秘钥 为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,我们需要定义一个用于加密解密的secret秘钥
  • 当生成JWT字符串的时候,需要使用secret秘钥对用户的信息进行加密,最终得到加密好的JWT字符串
  • 当把JWT字符串解析还原成JSON对象的时候,需要使用secret秘钥进行解密
//secret 的密钥本质:就是一个字符串
const secretKey = 'yiquersanli( ̄▽ ̄)/'

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

app.post('/api/login',(req,res)=>{
//将req.body请求体中的数据转存为userinfo常量
const userinfo = req.body
//登陆失败
if(userinfo.username !=='admin' || userinfo.password!=='0000000'){
    return res.send({
        status:400,
        message:'登陆失败!',
    })
}
//登陆成功
//用户登陆成功之后,调用jwt.sign()方法生成JWT字符串。并通过token属性发送给客户端
//参数1:用户的信息对象
//参数2:加密的密钥
//参数3:配置对象,可以配置当前token的有效期,秒:s,小时:h
//注意:千万不要将密码加密到token字符串中
const tokenStr = jwt.sign({username:userinfo.username},secretKey,{expiresIn:'30s'})

res.send({
    status:200,
    message:'登陆成功',
    //调用jwt.sign()生成JWT字符串,三个参数分别是:用户信息对象,加密秘钥,token有效期
    token:tokenStr,//要发送给客户端的token字符串
})
})
  1. 将JWT字符串还原为JSON对象 客户端每次在访问哪些有权限接口的时候,都需要主动通过请求头中的Authorization字段,将Token字符串发送到服务器进行身份认证。
    此时,服务器中可以通过express-jwt这个中间件,自动将客户端发送过来的Token解析还原成JSON对象:
//使用App.use()来注册中间件
//expressJWT({secret:secretKey})就是用来解析Token的中间件
// .unless({path:[/^/api\//]})来指定哪些接口不需要访问权限
//path:[/^/api\//]:以/api/开头的接口都不需要权限即可访问
app.use(expressJWT(secret:secretKey).unless({path:[/^\/api\//]}))
  1. 使用req.user获取用户信息 当express-jwt这个中间件配置成功后,即可在那些有权限的接口中,使用req.user对象,来访问从JWT字符串中解析出来的用户信息了

  2. 捕获解析JWT失败后产生的错误 当时用express-jwt解析Token字符串时,如果客户端发送过来的Token字符串过期不合法,会产生一个解析失败的错误,影响项目的正常运行。我们可以通过Express的错误中间件,捕获这个错误并进行相关的处理

app.use((err,req,res,next)=>{
    //token解析失败导致的错误
    if(err.name === 'UnauthorizedError'){
        return res.send({status:401,message:'无效的token'})
    }
    //其它原因导致的错误
    res.send({status:500,message:'未知错误'})
})