Node Express Passport (JWT) - 认证后回调

Ton*_*nes 3 javascript node.js express jwt passport.js

我使用护照 JWT 进行身份验证,但只有在用户通过身份验证时才能运行回调函数/响应。如何才能做到这一点?

在我的路线中:

import express from 'express';
import passport from '../../config/passport';
import memberInfoCtrl from '../controllers/memberInfo';

const router = express.Router();

router.route('/members')
  .get(membersCtrl.tokenCheck, passport.authenticate('jwt', { session: false }), membersCtrl.doSomethingElse);

export default router;
Run Code Online (Sandbox Code Playgroud)

membersCtrl.doSomethingElse如果身份验证成功,我想运行。

这是我的 tokenCheck 函数:

function tokenCheck(req, res, next) {
  const token = getToken(req.headers);
  if (token) {
    const decoded = jwt.decode(token, config.secret);
    User.findOne({
      email: decoded.email
    }, (err, user) => {
      if (err) throw err;

      if (!user) {
        return res.status(403).send({
          success: false, msg: 'Authentication failed. User not found.'
        });
      }
      // res.json({ success: true, msg: 'Welcome to the member area!' });
      return next();
    });
  } else {
    return res.status(403).send({ success: false, msg: 'No token provided.' });
  }
}
Run Code Online (Sandbox Code Playgroud)

使用res.jsonintokenCheck工作正常,但doSomethingElse之后没有调用该函数。

我认为这是因为我们发送了这样的响应:

res.json({ success: true, msg: 'Welcome to the member area!' });

替换res.jsonwithreturn next();返回错误:

Error: Unknown authentication strategy \"jwt\"

为什么会发生这种情况 - 在执行另一个函数之前,我如何检查身份验证?

我确定这是我错过的一些愚蠢的东西。任何帮助表示赞赏!

这是我初始化护照的主要快递脚本的一部分:

import passport from 'passport';
...
app.use(passport.initialize());

app.use('/api', routes);
...
Run Code Online (Sandbox Code Playgroud)

护照配置:

const JwtStrategy = require('passport-jwt').Strategy;
import User from '../server/models/user';
import config from './env';

module.exports = (passport) => {
  const opts = {};
  opts.secretOrKey = config.secret;
  passport.use(new JwtStrategy(opts, (jwtPayload, done) => {
    User.findOne({ id: jwtPayload.id }, (err, user) => {
      if (err) {
        return done(err, false);
      }
      if (user) {
        done(null, user);
      } else {
        done(null, false);
      }
    });
  }));
};
Run Code Online (Sandbox Code Playgroud)

Jon*_*kel 5

你的一般方法是正确的。为了根据某些条件保护路由,next()如果满足这些条件,请编写自定义中间件调用。

但是在您的情况下,这不是必需的,因为这就是这样passport-jwt做的。因此,假设您配置passportpassport-jwt正确地编写了以下所有内容:

router.route('/members')
    .get(passport.authenticate('jwt', { session: false }), membersCtrl.doSomethingElse);
Run Code Online (Sandbox Code Playgroud)

passport-jwt将从请求中提取 JWT 并根据您提供的秘密或密钥对其进行验证。之后它将使用护照的verify回调来填充req.user)。

另外:是的,在res.json()发送使用响应后,这就是为什么在这种情况下无法访问您的护照中间件和其他任何内容的原因。

关于您的错误Error: Unknown authentication strategy \"jwt\":如果您没有正确配置护照身份验证,通常会发生这种情况。如果您将它包含在您的问题中,我会查看它并相应地扩展我的答案。

更新:除了一件事之外,您的代码对我来说看起来不错:您没有jwtFromRequestpassport-jwt选项中指定必需的属性。或者您是否有机会忘记调用您的护照配置?

更新 2:关于我在下面的评论的进一步说明:
1. ) 在您的主要 express 脚本中导入您的 ES6 护照配置模块(您添加jwtFromRequest选项的位置)并调用它:

import passport from 'passport';
import passportConfig from 'path/to/passport/config';
...
app.use(passport.initialize());
passportConfig(passport);
...
Run Code Online (Sandbox Code Playgroud)

2.) 确保删除您的tokenCheck功能,您不需要它。请参阅此答案的第一部分。

更新 3: “未经授权”很棒,因为这意味着您现在成功地保护了您的/members路线。要实现基于令牌的身份验证,您现在需要一个额外的路由/authenticate,用户可以在其中请求访问您的 Web 服务,例如通过提供凭据(您的路由将验证这些凭据并使用 JWT 进行响应,该 JWT 必须使用您正在使用的相同机密进行签名passport-jwt- 否则passport-jwt稍后将无法验证令牌签名)。

但这超出了这个问题的范围。应该有很多资源可以涵盖这一点。例如,您可以/authenticate使用本文中jsonwebtoken所示的路由来实现(它们根本不使用,而是用于令牌创建验证)。passportjsonwebtoken

注意:如果你还实现了一个客户端,你必须在那里包含一些额外的逻辑来存储 JWT 并将它包含在你对 express 应用程序的请求中。

  • “之后它将使用护照的验证回调来填充 req.user”。那部分是黄金:) 看起来很简单,但实际上 Passport 并没有很好地记录它。 (2认同)