安装jwt相关的包两个:jsonwebtoken \ express-jwt
jsonwebtoken :作用生成JWT字符串(在服务器中将用户的信息转成JWT字符串)
express-jwt:将JWT字符串解析还原成JSON对象(从客户端保留的JWT加密字段 使用此包将用户的信息还原成真正的用户信息)
首先 新建文件夹:然后运行npm init -y 生成 package.json
之后安装需要的包 npm i jsonwebtoken 和 npm i express-jwt——全部需要的包
安装包使用空格将所有与的包进行分隔开 一起导入
const jwt=require('jsonwebtoken')//生成JWT
const expressJWT=require('express-jwt')//解析JWT
定义secret密钥
为了保证JWT字符串的安全性,防止jwt字符串传输的过程中别人破解,我们需要专门定义一个用于加密和解密的secret密钥:
- 当生成JWT字符串的时候,需要使用secret密钥对用户的信息进行加密,最终得到加密好的JWT字符串
- 当把JWT字符串解析还原成JSON对象的时候,需要对secret密钥进行解密(使用和前面加密相同的密钥)
如果定义:secret密钥的本质是一个字符串,所以定义字符串就可以
const secretKey=abdbdodjod-^-^-'
如何在登录成功后生成JWT字符串——生成Token
调用jsonwebtoken包中的sign()方法,将用户的信息加密生成JWT字符串,响应给客户端
sign({用户信息对象,密钥,配置对象(里面可配置expireIn:'30s' 指定token字符串的有效期)})
//用户信息对象 密钥 有效期
const tokenStr= jwt.sign(
{username:req.body.username},secretKey,{expiresIn:'30'}//30=30秒 30h=30小时
)
将JWT字符串还原成为JSON对象——解析Token
客户端每次访问有权限的接口的时候,都需要主动通过请求头的Authorization字段,将Token字符串发送到服务器进行身份认证。此时我们调用express-jwt中间件,自动将客户端发送过来的Token解析还原成JSON对象:
app.use()注册中间件
expressJWT({secret:secretKey}) 使用密钥解析Token的中间件
.unless({patn:[/^\/api\//]}) 用来指定哪些接口不需要访问权限----正则表达式 /api开头的
使用req.user(req.auth)获取用户信息——有权限的接口
使用express-jwt这个中间件配置成功后,即可在那些有权限的接口中,使用req.user对象,来访问JWT字符串中解析出来的用户信息——正常情况下,req里面是没有属性的,当配置解析token的中间件完成后,会自动将解析出来的用户信息挂载到req.user上————express-jwt - npm
查看最新文档
安装的第三方包
app.js(登录成功之后加密用户的信息对象——为了保证安全性 不要将密码进行加密——
//HS256 使用同一个「secret_key」进行签名与验证
//RS256 是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。
)
注意发送响应头的时候需要加上Bearer空格
//导入express模块
const express=require('express')
//创建web服务器
const app=express()
const jwt=require('jsonwebtoken')//生成JWT
var { expressjwt: expressJWT } = require("express-jwt");//解析JWT
//解决接口跨域问题
const cors=require('cors')
app.use(cors())
//配置解析表单数据的中间件 POST请求
app.use(express.urlencoded({extended:false}))
//定义secret密钥
const secretKey='--234--'
//挂载路由
//HS256 使用同一个「secret_key」进行签名与验证
//RS256 是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。
app.use( expressJWT({secret:secretKey,algorithms: ["HS256"]}).unless({path:[/^\/api\//]}))// /匹配的内容/ ^不在\转义/api/
app.post('/api/login',(req,res)=>{
//判断用户提交的登录信息是否正确
if(req.body.username !=='admin'||req.body.password!=='0000'){
return res.send(
{status:400,msg:'登录失败'}
)//服务器发送给客户端
}
//登录成功之后加密用户的信息对象——为了保证安全性 不要将密码进行加密
//否则token泄露 你的密码也泄露了
//用户信息对象 密钥 有效期
const tokenStr= jwt.sign(
{username:req.body.username,a:req.body.hello},secretKey,{expiresIn:'1h'}//30=30ms 30h=30小时 我设置的比较长 为了防止我使用get命令太慢了
)
//登录成功生成jwt字符串
res.send({status:202,
msg:'登录成功',
token:tokenStr,//要发送给客户端的token字符串
})//服务器发送给客户端状态
})
//有权限
app.get('/admin/getinfo',(req,res)=>{
console.log(req.auth)
res.send({
status:200,
message:'获取用户信息成功',
data:req.auth,//要发送给客户端的用户信息
})
})
//启动服务器、使用80端口
app.listen(8888,()=>{
console.log('http://127.0.0.1:8888 启动成功')
})
捕获解析JWT(即解析token)失败后产生的错误——错误中间件在最后 进行捕获错误
当使用express-jwt解析Token字符串时,如果客户端发送过来的Token字符串过期或不合法,会产生一个解析失败的错误,影响项目的正常运行,可以通过Express的错误中间件,捕获这个错误并进行相关的处理
app.use---err.name==UnauthorizeError——Token解析失败
//全局中间件
app.use(function (err, req, res, next) {
if (err.name === "UnauthorizedError") {
res.send({
status:401,
message:'无效的Token',
})
}
res.send({
status:500,
message:'未知的错误',
}
)
});
//导入express模块
const express=require('express')
//创建web服务器
const app=express()
const jwt=require('jsonwebtoken')//生成JWT
var { expressjwt: expressJWT } = require("express-jwt");//解析JWT
//解决接口跨域问题
const cors=require('cors')
app.use(cors())
//配置解析表单数据的中间件 POST请求
app.use(express.urlencoded({extended:false}))
//定义secret密钥
const secretKey='--234--'
//挂载路由
//HS256 使用同一个「secret_key」进行签名与验证
//RS256 是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。
app.use( expressJWT({secret:secretKey,algorithms: ["HS256"]}).unless({path:[/^\/api\//]}))// /匹配的内容/ ^不在\转义/api/
app.post('/api/login',(req,res)=>{
//判断用户提交的登录信息是否正确
if(req.body.username !=='admin'||req.body.password!=='0000'){
return res.send(
{status:400,msg:'登录失败'}
)//服务器发送给客户端
}
//登录成功之后加密用户的信息对象——为了保证安全性 不要将密码进行加密
//否则token泄露 你的密码也泄露了
//用户信息对象 密钥 有效期
const tokenStr= jwt.sign(
{username:req.body.username,a:req.body.hello},secretKey,{expiresIn:'60s'}//30=30ms 30h=30小时 我设置的比较长 为了防止我使用get命令太慢了
)
//登录成功生成jwt字符串
res.send({status:202,
msg:'登录成功',
token:tokenStr,//要发送给客户端的token字符串
})//服务器发送给客户端状态
})
//有权限
app.get('/admin/getinfo',(req,res)=>{
console.log(req.auth)
res.send({
status:200,
message:'获取用户信息成功',
data:req.auth,//要发送给客户端的用户信息
})
})
//全局中间件
app.use(function (err, req, res, next) {
if (err.name === "UnauthorizedError") {
res.send({
status:401,
message:'无效的Token',
})
}
res.send({
status:500,
message:'未知的错误',
}
)
});
//启动服务器、使用80端口
app.listen(8888,()=>{
console.log('http://127.0.0.1:8888 启动成功')
})