如果在passport.authenticate(...)上删除(req,res,next),网页将无限期地加载

时间:2018-06-13 23:06:01

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

我从互联网上下载了一个示例项目。下面是代码的一些片段:

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', ...,而不是在同一行中使用它们?< / p>

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

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

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

  3. 谢谢!

1 个答案:

答案 0 :(得分:0)

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

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

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

原因是重要的是使用res参数发送响应允许express通过调用{{1}继续到下一层中间件/ etc回调参数。它全部异步发生,并使用回调来指示流。

next()

req.user将是以前登录的用户,我相信passport.js通常使用var checkJwt = function(req, res, next) { passport.authenticate( 'jwt', {session: false }, function (err, user, info) { next(); } )(req, res, next); } 包存储。