最近想要给我的博客系统添加一个基于node.js服务器的token身份验证的功能,要求用户进行登录操作后的3小时内可以进行评论操作,但登录超过3小时则要重新进行登录,否则不能对文章进行评论。
废话不多说,直接说方法:
1. 来到node.js服务端,需要额外下载的插件
npm i express-jwt --save
npm i jsonwebtoken --save
2. 在router.js中引入
const jwt = require('jsonwebtoken');
const { format } = require('path');
const SECRET_KEY = 'login2022';
3. 当用户第一次登录成功之后,服务端给客户端返回相关资源的同时生成并发送一串token命令
// 这是一个常规的登录接口
router.post('/api/login', function (req, res) {
let { body } = req
var sqlStr = `SELECT * FROM usermanage WHERE user_name='${body.user_name}' AND user_password='${body.user_password}'`;
conn.query(sqlStr, function (err, results) {
if (err) {
res.json({ code: 1, msg: err });
}
else {
if (results.length == 0) {
res.json({ code: 2, msg: '未找到该用户' });
} else {
// 以上是常规的登录流程,查找数据库是否有用户的信息,以下是添加token的流程
// 如果登录成功,则用jwt.sign签署token令牌,最基本的令牌由用户的基本信息 + 一个自定义的字符串 + 有效时间 构成, 也可以加上当前时间戳
let token = jwt.sign(
{ user: { name: results[0].user_name, password: results[0].user_password } }, //用户信息
SECRET_KEY, //自定义字符串
{ expiresIn: '3h' } //有效时间,这里我设置3个小时
)
res.json({ code: 0, list: results, token }); //最后,将资源和token令牌一并发送给客户端。
}
}
});
});
4. 接下来来到前端部分,客户端将从后端传递过来的token令牌存储到本地
localStorage.setItem("token", res.data.token);
5. 然后,对我们的请求方法进行一个封装,要求每一个前端向服务器发请求时,都要发送一个包含token的Authorization请求头
以下是我自己项目的封装方法
const $http = axios.create({
baseURL: 'http://localhost:3000/api',
timeout: 5000,
//下面是重点
headers: {
'Content-Type': "application/json;charset=utf-8",
//注意:这个Bearer是必需的,如果后端没有添加 'Bearer ', 则需要前端自己拼接
//从本地获取token
'Authorization': 'Bearer '+ window.localStorage.getItem('token')
}
})
好了,现在前端部分已经搞定了,我们返回后端进行下一步操作。
在服务端新建一个errorhandler文件,里面写入以下方法,生成一个专门发送token错误的中间件:
function errorHandler(err, req, res, next) {
console.log(err, err.name);
let code = 500;
let message = 'Internal Server Error';
// token解析的错误
if (err.name === 'UnauthorizedError') {
code = 401
message = 'no login'
}
res.statusCode = code;
res.send({
status: code,
message,
})
}
module.exports = errorHandler
6. 来到服务器的入口文件index.js,引入插件
//创建服务器
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
//引入parseJwt
const parseJwt = require("express-jwt");
//引入token错误中间件
const errorhandler = require('./errorhandler')
7. 对从服务器返回的token令牌进行解析
//这里是对所有的请求接口都进行token验证
app.use(parseJwt({
secret: 'login2022', // 生成token时的 钥匙,必须统一
algorithms: ['HS256'] // 必填,加密算法
}).unless({
path: ['/api/login'] // 一般来说,登录接口不需要进行token验证,所以可以用.unless避免对该接口的验证,当然也可以添加其它的接口
}));
//使用token错误中间件,如果token失效或过期,则向前端发送相关报文
app.use(errorhandler)