无法进入下一个中间件——NodeJS
Posted
技术标签:
【中文标题】无法进入下一个中间件——NodeJS【英文标题】:Can't go to the next middleware - NodeJS 【发布时间】:2021-02-04 11:30:03 【问题描述】:我正在使用express
和router
创建具有公共和私有路由的服务器。要访问私有路由,用户必须登录并发送JWT
令牌。令牌很好,但我无法将用户重定向到私有路由。
const express = require('express');
const jwt = require('jsonwebtoken');
const authRouter = require('./auth');
const usersRouter = require('./users');
const router = express.Router();
router.use(authRouter);
const accessTokenSecret = '4-8-15-16-23-42';
const privateRoutes = ['/user'];
const checkPublicOrPrivate = (req, res, next) =>
privateRoutes.forEach(route =>
if (req.path.includes(route))
return authorization(req, res, next);
);
return next();
;
const authorization = (req, res, next) =>
const token = req.headers;
if (token)
jwt.verify(token, accessTokenSecret, (err, user) =>
if (err)
return res.status(403).send('Forbiden, access denied');
console.log(user); // username: 'username', iat: 1603288443
return next(); //Should go to the next middleware
);
return res.status(403).send('Bad message') //But always hits this message or the 404 one
;
router.use(checkPublicOrPrivate);
router.use(authorization); //Also tried without this line
router.use(usersRouter);
router.use(function(req, res, next)
res.status(404).send('404 not found!');
);
router.use(function(err, req, res, next)
res.status(500).send('Server error');
);
module.exports = router;
【问题讨论】:
【参考方案1】:那是因为jwt.verify
是异步的(它有一个回调函数)。
在验证您的令牌时,代码会继续执行。下一行要执行的是res.status(403).send('Bad message')
,所以它总是被执行。
解决方案是将该行包装在 else
语句中
const authorization = (req, res, next) =>
const token = req.headers;
if (token)
jwt.verify(token, accessTokenSecret, (err, user) =>
if (err)
return res.status(403).send('Forbiden, access denied');
console.log(user);
return next();
);
else // add 'else'
res.status(403).send('Bad message'); // This line will only be executed if there's no token
;
【讨论】:
谢谢,403 消息消失了,但它以某种方式跳过router.use(userRouter)
并转到 404 中间件,是因为 jwt.verify 的异步行为吗?
这是另一个问题。您为每个请求定义了一个 res.status(404).send('404 not found!')
的中间件。该函数仅执行此操作。因此,每个请求都会得到 404。我相信我对两个问题的解决值得被标记为已接受的答案? :)【参考方案2】:
你应该尝试类似的方法
// the middleware
authenticateToken = function (req, res, next)
const cookie = new Cookie(req ,res , )
const token = cookie.get('access_token',signed:false)
if (token == null) res.redirect('login',401); //TODO: redirect to login with a small message
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) =>
if (err)
authMethods.refreshToken(req,res,next);
else
req.user = user
next()
)
然后在你的路线中
// the route ...
router.get('/', authenticateToken, function (req, res, next)
if (!req.user.email)
res.render('login', message: "please login again" );
const userEmail = authMethods.data.dailyReportNameTable(req.user.email)
console.log(userEmail)
res.render(userEmail)
);
【讨论】:
以上是关于无法进入下一个中间件——NodeJS的主要内容,如果未能解决你的问题,请参考以下文章
nodejs 中使用mysql数据有没有类似 mongoose 的中间件