切换主题
十五、在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:"未知的错误"
})
})