JWT(JsonWebToken)
一、安装JWT相关的包
npm install jsonwebtoken express-jwt
- jsonwebtoken:用于生成JWT字符串,将用户信息转化为JWT字符串
- express-jwt:用于将JWT字符串(客户端发送到服务器端)解析还原成包含用户信息的JSON对象
二、导入JWT相关的包
使用require()函数,分别导入JWT相关的两个包
// 1.导入用户生成JWT字符串的包
const jwt = require('jsonwebtoken')
// 2.导入用于将客户端发送过来的JWT字符串,解析还原称JSON对象的包
const expressJWT = require('express-jwt')
三、定义secret秘钥
为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,需要专门定义一个用于加密和解密的secret秘钥:
- 当生成JWT字符串的时候,需要使用secret秘钥对用户的信息进行加密,最终得到加密好的JWT字符串
- 当把JWT字符串捷信还原称JSON对象的时候,需要使用secret秘钥进行解密
// 3.secret 秘钥的本质:就是一个字符串, 值可以随便写, 越复杂越好
const secretKey = 'secret test'
四、在登录成功后生成JWT字符串
调用jsonwebtoken包提供的sign()方法,将用户的信息加密成JWT字符串(尽量别把例如密码的敏感信息加密到token,有风险),响应给客户端:
app.post('/api/login', function(req, res) {
// 用户登录成功之后,生成JWT字符串,通过token属性响应给客户端
res.send({
status: 200,
message: '登录成功',
//调用jwt.sign()生成JWT字符串,三个参数分别为:有效载荷payLoad(是个对象,包含用户信息,这里暂用userInfo代替)、加密秘钥、配置对象(例如:expiresIn 表示token的有效期)
token: jwt.sign(userInfo, secretKey, {expiresIn: '30s'})
})
})
五、将JWT字符串还原为JSON对象
客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的Authrization字段,将Token字符串发送到服务器进行身份认证。
此时,服务器可以通过express-jwt这个中间件,自动将客户端发送过来的Token解析还原成JSON对象:
// 使用app.use()来注册中间件
// expressJWT({ secret: secretKey }) 就是用来解析Token的中间件(secret用来解密)
// .unless({ path: [/^\/api\//] }) 正则表达式指定哪些以api为前缀的接口不需要访问权限
app.use(expressJWT( { secret: secretKey }).unless({ path: [/^\/api\//] }) )
只要配置成功了express-jwt这个中间件,就可以把解析出来的用户信息,挂载到req上(解密成功,req上多了user属性:req.user)
六、使用req.user获取用户信息
当express-jwt这个中间接配置成功之后,即可在那些有权限的接口中,使用req.user对象,来访问从JWT字符串中解析出来的用户信息:
//这是一个有权限的接口
app.get('/admin/getinfo', function(req, res) {
console.log(req.user)
res.send({
status: 200,
message: '成功获取用户信息!!!',
data: req.user
})
})
七、捕获解析JWT失败后产生的错误
当使用express-jwt解析Token字符串时,如果客户端发送过来的Token字符串过期或不合法,会产生一个解析失败的错误,影响项目的正常运行。可以通过Express的错误中间件,捕获这个错误并进行相关的处理:
app.use((err, req, res, nest) => {
//token解析失败导致的错误
if(err.name === 'UnauthorizedError') {
return res.send({ status: 401, message: '无效的token' })
}
//其他原因导致的错误
res.send({ status: 500, message: '未知错误' })
})