前言
做过前后端分离项目的同学应该都做过 token 验证,在前端登录的时候需要缓存后端传过来的 token,然后在需要验证权限的接口带上 token。本章节来实现使用 node 进行 token 的权限验证。
技术准备
1、express
应用中使用了 express 框架,安装过程可查看
https://blog.csdn.net/weixin_43930421/article/details/125926741
2、安装 jsonwebtoken 和 express-jwt
npm install jsonwebtoken express-jwt
jsonwebtoken 用来转换用户 json 信息为 token 串,express-jwt 则用来解析 json 进行验证。
3、MySQL
安装过程可查看
https://www.runoob.com/mysql/mysql-install.html
初学者建议安装5.7版本,8.0以上需要爬坑。
4、Redis
本节可忽略,但是如果需要实现单设备登录、或者单点登录功能,需要在 redis 中为用户保留一份 token信息。
安装教程查看
https://www.runoob.com/redis/redis-install.html
后端代码实现
先看入口文件 app.js
app.js
const express = require("express");
const app = express();
const port = 3000
var path = require('path');
const {
expressjwt} = require('express-jwt')
require("./config.js");
const Redis = require('./utils/redis.js');
// 解析 post 请求的 body 体
app.use(express.urlencoded({
extended: false}));
app.use(express.json())
var server = require('http').Server(app);
// 写在前面的路由不进行拦截
app.use("/account", require("./router/account.js")); // 登录相关页面路由
app.use("/mine", require("./router/mine.js")); // 我的页面路由
// 设置不需要验证的接口
let noAuth = ['/api/regist', '/api/login'];
// token 拦截
app.use(expressjwt({
secret: global.config.SECRET_KEY, algorithms: ['HS256'] }).unless({
path: noAuth }))
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
res.status(401).send('invalid token')
}
})
// 验证 redis ------ 可以忽略,感兴趣的后期加上
app.use(function (req, res, next) {
let url = req.url;
if(noAuth.find(item=>{
return item == url;
})){
next();
return;
}
// 过滤不需要验证的接口
let userID = req.auth.userID;
let token = req.headers.authorization;
let redisClient = new Redis();
redisClient.getKey(`token_${
userID}`).then(val => {
// 判断是否过期
if(val && token == val){
next();
}else{
res.status(401).send('invalid token')
}
})
})
// api 接口文件,和路由分开
app.use("/api", require("./router/api.js"));
server.listen(port, () => {
console.log(`Example app listening on port ${
port}`)
})
页面引用了 config.js,这个页面主要是配置一些公共信息,存入 global 全局变量中。
config.js
global.config = {
SECRET_KEY: 'just do it'
}
redis.js 实现了对 redis 字符串操作的封装,一个是读取 key 的值,一个是设置 key 的值和失效时间。
redis.js
const redis = require('redis')
const client = redis.createClient(6379,'localhost')
function redisClient(){
this.getKey =