无法进入下一个中间件——NodeJS

Posted

技术标签:

【中文标题】无法进入下一个中间件——NodeJS【英文标题】:Can't go to the next middleware - NodeJS 【发布时间】:2021-02-04 11:30:03 【问题描述】:

我正在使用expressrouter 创建具有公共和私有路由的服务器。要访问私有路由,用户必须登录并发送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相关浅谈NodeJS中间件

Nodejs之使用express框架搭建WEB应用

nodejs 中使用mysql数据有没有类似 mongoose 的中间件

如何使用nodejs作为java和前端的中间件

nodejs 中使用mysql数据有没有类似 mongoose 的中间件

NodeJs 中间件集标头