【问题标题】:Passport.js authentication middleware with Node.js带有 Node.js 的 Passport.js 身份验证中间件
【发布时间】:2020-12-31 21:18:35
【问题描述】:

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

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

一开始,我把所有的逻辑都放在控制器里。

但是所有安全路由器都需要检查认证,所以我尝试将认证部分划分为中间件


之前

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. 这是在中间件之间传递数据的正确方法吗?还是有更好的方法?

【问题讨论】:

    标签: javascript node.js express authentication passport.js


    【解决方案1】:

    这是使用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 使用未加密的令牌数据自动填写 req.user,以防令牌有效 (If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.)。你通常应该有用户电子邮件(到req.user),以防你用你的电子邮件伪造令牌。
    【解决方案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) {
            
        }
    };
    

    【讨论】:

    • 谢谢。但是我还是想知道这种方式好不好。
    • @hyojoon 这有什么问题?
    猜你喜欢
    • 2023-04-05
    • 2015-06-06
    • 2020-03-23
    • 2018-03-08
    • 2014-10-25
    • 2018-04-19
    • 2014-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多