文章目录
- 在Express中使用JWT
- 1 安装JWT相关的包
- 2 导入JWT相关的包
- 3 定义secret密钥
- 4 在登录成功后生成JWT字符串
- 5 将JWT字符串还原为JSON对象
- 6 使用req.user获取用户信息
- 7 捕获解析JWT失败后产生的错误
- 8 完整代码示例
在Express中使用JWT
1 安装JWT相关的包
运行如下命令,安装如下两个JWT相关的包:
npm install jsonwebtoken express-jwt
其中:
- jsonwebtoken用于生成JWT字符串
- express-jwt用于将JWT字符串解析还原成Json对像
2 导入JWT相关的包
// 1.导入用于生成JT字符串的包
const jwt = require('jsonwebtoken')
//2.导入用于将客户端发送过来的JwT字符串,解析还原成JS0N对象的包
const { expressjwt: jwt } = require("express-jwt");
3 定义secret密钥
为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,我们需要专门定义一个用于加密和解密的secret密钥:
- 当生成JWT字符串的时候,需要使用secret密钥对用户的信息进行加密,最终得到加密好的JWT字符串
- 当把JWT字符串解析还原成json对象的时候,需要使用secret密钥进行解密
密钥可以是任意的字符串,越复杂越好
//3.secret密钥的本质:就是一个字符串
const secretKey = 'Nodejs No1 ^_^'
4 在登录成功后生成JWT字符串
调用jsonwebtoken
包提供的sign()
方法,将用户的信息加密成JWT字符串,响应给客户端:
千万不要把密码加密到token中
//登录接口
app.post('/api/login', (req, res) => {
// ··省略登录失败情况下的代码
//用户登录成功之后,生成JWT字符串,通过token属性响应给客户端
res.send({
status: 200,
message: '登录成功!',
//调用jwt.sign()生成JWT字符串,三个参数分别是:用户信息对像、加密密钥、配置对橡
token: jwt.sign({username: userinfo.username}, secretKey, {expiresIn: '30s'})
})
})
完整代码:
const express = require("express")
const jwt = require("jsonwebtoken")
const {urlencoded} = require("express");
const app = express()
app.use(urlencoded({extended: false}))
const secretKey = "kkk *_*"
app.get("/login", (req, res) => {
if (req.body.username === 'admin' && req.body.password === 'admin') {
const tokenStr = jwt.sign({username: req.body.username}, secretKey, {expiresIn: "24h"})
res.send({
status: 200,
msg: 'success',
token: tokenStr
})
} else {
req.send({
msg: "账号或者密码错误"
})
}
})
app.listen(80, () => {
console.log("server start")
})
启动后通过接口测试,得到结果如下:
5 将JWT字符串还原为JSON对象
客户端海次在访问那些有权限接口的时候,都需要主动通过请求头中的Authorization字段,将Token字符串发送到服务器进行身份认证。
此时,服务器可以通过express-jwt
这个中间件,自动将客户端发送过来的Token解析还原成json对像:
express-jwt7版本之后用法发生了变化,参考express-jwt - npm
const { expressjwt } = require("express-jwt");
// 使用app.use()来注册中间件
// .unless({path:[/^\/api\//]})用来指定哪些接口不需要访问权限
app.use(
expressjwt({
secret: secretKey,
algorithms: ["HS256"]
}).unless({path: [/^\/api\//]})
)
6 使用req.user获取用户信息
当express-jwt
这个中间件配置成功之后,即可在那些有权限的接口中,使用req.user
对象,来访问从JWT字符串中解析出来的用户信息了,示例代码如下:
只有配置好了
express-jwt
中间件之后才能通过req.user
获取用户信息,
//这是一个有权限的API接口
app.get('/admin/getinfo', (req, res) => {
console.log(re.user)
res.send({
status: 200,
message: '获取用户信息成功!',
data: req.auth
})
})
7 捕获解析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: '未知错误'})
})
8 完整代码示例
const express = require("express")
const jwt = require("jsonwebtoken")
const {urlencoded} = require("express");
const {expressjwt} = require("express-jwt")
const app = express()
const secretKey = "kkk *_*"
app.use(urlencoded({extended: false}))
app.use(
expressjwt({
secret: secretKey,
algorithms: ['HS256']
}).unless({path: [/^\/api\//]})
)
app.get("/api/login", (req, res) => {
if (req.body.username === 'admin' && req.body.password === 'admin') {
const tokenStr = jwt.sign({username: req.body.username}, secretKey, {expiresIn: "24h"})
res.send({
status: 200,
msg: 'success',
token: tokenStr
})
} else {
req.send({
msg: "账号或者密码错误"
})
}
})
app.get("/user/getInfo", (req, res) => {
res.send({
status: 200,
msg: "success",
data: res.auth
})
})
app.listen(80, () => {
console.log("server start")
})
app.use((err, req, res, next) => {
//token解析失败导致的错误
if (err.name === 'UnauthorizedError') {
return res.send({status: 401, message: '无效的token'})
}
//其它原因导致的错误
res.send({status: 500, message: '未知错误'})
})
登录结果:
获取信息成功结果:
记得将登陆中得到的token放到Authorization中,并且前面加上Bearer
token有误的情况: