Passport.js 身份验证中间件 Node.js

Passport.js authentication middleware with Node.js

我正在尝试通过在 Node.js 服务器上使用 jsonwebtoken 来制作 安全路由器

我正在使用 passport.js 通过 JWT 对用户进行身份验证。

一开始,我把所有的逻辑都放在controller里面。

但是所有secure routers都需要检查认证,所以我尝试将认证部分划分为一个中间件


之前

user.controller.js

/**
 * GET /user
 * Get user data
 */
 exports.getUser = (req, res, next) => {
   passport.authenticate("jwt", { session: false }, (err, payload, info) => {
     if (err) return next(err);
     if (!payload) return next(info);
 
     User.findOne({ email: payload.email }, (err, user) => {
       if (err) return next(err);
       if (!user) return next("no matching user found");
       res.status(200).send({ email: user.email });
     });
   })(req, res, next);
};

app.js

const userController = require('user.controller.js');
app.get('/user', userController.getUser);

之后

passport.js

/**
 * Check authentication
 */
exports.checkAuth = (req, res, next) => {
  passport.authenticate("jwt", { session: false }, (err, payload, info) => {
    if (err) return next(err);
    if (!payload) return next(info);
    req.user = payload;
    next();
  })(req, res, next);
};

user.controller.js

/**
 * GET /user
 * Get user data
 */
exports.getUser = (req, res, next) => {
  User.findOne({ email: req.user.email }, (err, user) => {
    if (err) return next(err);
    if (!user) return next("no matching user found");
    res.status(200).send({ email: user.email });
  });
};

app.js

const passportConfig = require('passport.js');
const userController = require('user.controller.js');
app.get('/user', passportConfig.checkAuth, userController.getUser);

原来的 user.controller.js 我可以从 payload.email 得到 email

但是 分割原始文件后,我无法访问 user.controller.js 处的 email 值。

所以我搜索了一些如何将数据从一个中间件传递到另一个中间件的方法,并使用了req.user


问题

  1. 这是使用 jwt 进行身份验证的正确结构吗,passport.js?
  2. 这是在中间件之间传递数据的正确方法吗?还是有更好的方法?

控制器功能在检查中间件之前执行,请使用 Promisify doc

像下面这样更新您的中间件
const util = require('util');
const authenticate = util.promisify(passport.authenticate);

exports.checkAuth = async (req, res, next) => {
    // passport.authenticate("jwt", { session: false }, (err, payload, info) => {
    //     if (err) return next(err);
    //     if (!payload) return next(info);
    //     req.user = payload;
    //     next();
    // })(req, res, next);

    try {
        const payload = await authenticate("jwt", { session: false });
        req.user = payload;
        //Do something
        next();
    } catch (error) {
        
    }
};

这是使用 req 将数据从中间件传递给其他人的好习惯。

顺便说一下,您不应该自己从护照自定义回调中调用 next()(这不是中间件)。如果令牌有效,Passport 将自己调用下一个中间件。

/**
 * Check authentication
 */
exports.checkAuth = (req, res, next) => {
  passport.authenticate("jwt", { session: false }, (err, payload, info) => {
    if (err) return next(err);
    if (!payload) return next(new Error('wrong to'));
    //next()
  })(req, res, next);
};

从您的 "Before" 步骤来看,使用自定义回调是有原因的,因为您可以从中检查用户电子邮件是否存在。 但是从您的 "After" 步骤开始,用户检查逻辑已移至另一个中间件。所以你可以只使用护照默认中间件。

exports.checkAuth = passport.authenticate("jwt", { session: false });

然后 user.controller.js 将被调用,令牌数据绑定到 req.user,以防令牌被 Passport 验证。

此时,您可以进行邮箱验证。