【问题标题】:Web page keeps loading indefinitely if removing (req, res, next) on passport.authenticate(...)如果在 passport.authenticate(...) 上删除 (req, res, next),网页会无限期加载
【发布时间】:2018-06-15 04:16:48
【问题描述】:

我从 Internet 下载了一个示例项目。下面是部分代码片段:

routes 文件中,我有以下内容(只是一个片段):

var authController = require('./controllers/authController'),
var passport = require('passport');
var authLoginFacebook =
    passport.authenticate(
        'facebook',
        {
            session: false,
            scope: ['public_profile', 'email']
        }
    );
var checkJwt = function(req, res, next) {
    passport.authenticate(
        'jwt',
        {session: false },
        function (err, user, info) {
            next();
        }
    )(req, res, next);
}

module.exports = function(app) {
    // ...
    app.get(
        '/api/auth/login/facebook/callback',
        checkJwt,
        authLoginFacebook,
        authController.login
    );
    // ...
}

passport 文件中,我有以下内容(只是一个片段):

var User = require('../models/user');
var credentials = require('./credentials');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var LocalStrategy = require('passport-local').Strategy;
var FacebookStrategy = require('passport-facebook').Strategy;

module.exports = function(passport) {

    passport.use(
        new JwtStrategy({
                secretOrKey: credentials.secret,
                jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('JWT'),
            },
            function(payload, done) {
                User.findById(
                    payload._id,
                    function(err, user) {
                        if (err) {
                            return done(err, false);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            return done(null, false);
                        }
                    }
                );
            }
        )
    );

    var fbStrategy = credentials.facebook;
    fbStrategy.passReqToCallback = true;
    passport.use(new FacebookStrategy(fbStrategy,
        function(req, token, refreshToken, profile, done) {
            // asynchronous
            process.nextTick(function() {
                // check if the user is already logged in
                if (!req.user) {
                    User.findOne({
                        'facebook.id': profile.id
                    }, function(err, user) {
                        if (err)
                            return done(err);
                        if (user) {
                            // if there is a user id already but no token (user was linked at one point and then removed)
                            if (!user.facebook.token) {
                                user.facebook.token = token;
                                user.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
                                user.facebook.email = (profile.emails[0].value || '').toLowerCase();
                                user.save(function(err) {
                                    if (err)
                                        return done(err);
                                    return done(null, user);
                                });
                            }
                            return done(null, user); // user found, return that user
                        } else {
                            // if there is no user, create them
                            var newUser = new User();
                            newUser.facebook.id = profile.id;
                            newUser.facebook.token = token;
                            newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
                            newUser.facebook.email = (profile.emails[0].value || '').toLowerCase();
                            newUser.save(function(err) {
                                if (err)
                                    return done(err);
                                return done(null, newUser);
                            });
                        }
                    });
                } else {
                    // user already exists and is logged in, we have to link accounts
                    var user = req.user; // pull the user out of the session
                    user.facebook.id = profile.id;
                    user.facebook.token = token;
                    user.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
                    user.facebook.email = (profile.emails[0].value || '').toLowerCase();
                    user.save(function(err) {
                        if (err)
                            return done(err);
                        return done(null, user);
                    });
                }
            });
        })
    );

    // ...
};

我有几个问题:

  1. 为什么在:passport.authenticate('jwt', ... 上传递了这些参数:(req, res, next) 和在 passport.authenticate('facebook', ... 上,当它们在同一行中并排使用时不要?

    app.get(
        '/api/auth/login/facebook/callback',
        checkJwt,
        authLoginFacebook,
        authController.login
    );
    

    如果我删除这些参数,那么网页会无限期地加载。

  2. 为什么内部:passport.use(new FacebookStrategy 被定义为:req.user?在哪里声明了字段:user 对象 req

谢谢!

【问题讨论】:

    标签: node.js express passport.js passport-facebook passport-jwt


    【解决方案1】:

    *编辑:这是一个调用另一个函数的函数...这是必需的,因为回调使用了next()。 facebook 功能没有。

    换句话说,当您调用passport.authenticate 时,返回值实际上将是一个期望参数req, res, next 的函数。通常你不需要包装它,因为它可以工作。但是,在这种情况下,有一个回调函数作为参数传入,并且该回调函数需要访问 next 参数。因此,您必须包装整个内容才能访问该 next 参数。

    *注意:被包装的函数实际上并没有向/通过包装函数返回任何东西。 passport.authenticate() 返回一个函数,然后这个返回函数用后面的参数组自调用。但是这第二个自调用函数结果不会被捕获为变量或返回或任何东西。

    原因是重要的事情是要么使用res 参数发送响应 通过调用next() 回调参数允许express 继续到下一层中间件/等。这一切都是异步发生的,并且使用回调来引导流程。

    var checkJwt = function(req, res, next) {
        passport.authenticate(
            'jwt',
            {session: false },
            function (err, user, info) {
                next();
            }
        )(req, res, next);
    }
    

    req.user 将是以前登录的用户,我相信 passport.js 通常使用 express-session 包存储。

    【讨论】:

    • 您说:the return value is actually going to be a function expecting the parameters req, res, next,但函数:checkJwt 没有返回任何值,因为没有使用关键字:return。我觉得这里有什么我不明白的地方?
    • 你说得对,当我说“返回”时,我使用了错误的术语。 express 中的整个中间件链等都是异步运行的。返回什么并不重要。当一层中间件完成并希望允许进程继续到下一层时,它会调用next() 回调。如果它“拒绝”(用 Promise 的话来说),它会调用 res.end() 或类似的东西。
    猜你喜欢
    • 2019-10-27
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多