如果 header 中不存在 JWT 令牌,如何执行某些逻辑?

How to perform some logic if JWT token is not present in header?

我正在使用 passport-jwt 并且有一个端点,如果 header 中不存在 jwt 令牌,它应该 return 来自数据库的一些数据。 是否可以应用一些逻辑而不是仅仅发送未经授权的 401?

router.get(
    '/get/items',
    passport.authenticate('jwt', {session: false}),
    (req, res) => {
     // reaches this point only after validating token
     ...
    }
);

因此,如果存在 jwt 令牌,基于它的端点应该 return 一些数据。如果不是,应该 returned

来自 db 的一些其他数据

我认为 custom callback 是一个选项。它作为最后一个参数传递给 authenticate(strategy, options, callback) 方法,它将允许您设置您希望的行为。

您的代码将如下所示:

app.get('/get/items', (req, res, next) => {

    passport.authenticate('jwt', { session: false }, (err, user, info) => {
        if (!user) {
            /* 
                Unauthorized accees.
                Handle here the request as u wish
            */

            /* Do some custom logic and return your desired result */
            return res.status(401).json({ success: false, message: 'Unauthorized access!' });
        }

        /* User is authorized. Do other stuff here and return your desired result*/
        return res.status(200).json({ success: true, message: 'Congratulations!' });
    })(req, res, next);
    
});

In this example, note that authenticate() is called from within the route handler, rather than being used as route middleware. This gives the callback access to the req and res objects through closure.

If authentication failed, user will be set to false. If an exception occurred, err will be set. An optional info argument will be passed, containing additional details provided by the strategy's verify callback.

The callback can use the arguments supplied to handle the authentication result as desired. Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response.

Source

包装你的中间件并按你想要的方式处理错误:

function authenticate(req, res, next) {
  passport.authenticate('jwt', { session: false }, (err, user) => {
    if (err) {
      res.status(err.statusCode || 401).json({ error: err.toString() });
      return;
    }

    if (!user) {
      res.status(404).json({ ... });
      return;
    }

    req.user = user;

    next();
  })(req, res, next);
}

改用它:

router.get(
    '/get/items',
    authenticate,
    (req, res) => {
     // reaches this point only after validating token
     ...
    }
);

@codtex 和@Dominic 的回答解决了问题。

我发现以下解决方案也有效:

router.get(
    '/get/items',
    passport.authenticate('jwt', {session: false}),
    (req, res) => {
        // reaches this point only after validating token
        ...
    },
    (err, req, res, next) => {
        console.log('error handling');
        // reaches this point if validation fails
    }
);