在PassportJS中序列化不同类型的用户

时间:2016-11-23 07:00:23

标签: node.js mongodb serialization deserialization passport.js

我有两种不同类型用户的本地策略:学生和教师。我在尝试登录时遇到问题,因为我的序列化工作不正常。

我有两个模特,学生和老师。两者都有各自的集合,学生和教师具有类似的模式。两者都有类似的功能:

module.exports.getStudentByUsername = function(username, callback){
    var query = {username: username};
    User.findOne(query, callback);
}

module.exports.getStudentById = function(id, callback){
    User.findById(id, callback);
}

module.exports.comparePassword = function(candidatePassword, hash, callback){
    bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
        if(err) throw err;
        callback(null, isMatch);
    });
}

我的两个本地策略是:

passport.use('student-local', new LocalStrategy(
    function(username, password, done) {
        Student.getStudentByUsername(username, function(err, student){
            if(err) throw err;
            if(!student){
                return done(null, false, {message: 'Unknown Student'});
            }
            Student.comparePassword(password, student.password, function(err, isMatch){
                if(err) throw err;
                if(isMatch){
                    return done(null, student);
                } else {
                    return done(null, false, {message: 'Invalid password'});
                }
            });
        });
    }));

passport.use('teacher-local', new LocalStrategy(
    function(username, password, done) {
        Teacher.getTeacherByUsername(username, function(err, teacher){
        if(err) throw err;
        if(!teacher){
            return done(null, false, {message: 'Unknown Teacher'});
        }
        Teacher.comparePassword(password, teacher.password, function(err, isMatch){
                if(err) throw err;
                if(isMatch){
                    return done(null, teacher);
                } else {
                    return done(null, false, {message: 'Invalid password'});
                }
            });
        });
    }));

我的两次登录是:

router.post('/loginStudent',
passport.authenticate('student-local', {successRedirect:'/users/student', failureRedirect:'/login',failureFlash: true}),
function(req, res) {
    res.redirect('/');
});

router.post('/loginTeacher',
passport.authenticate('teacher-local', {successRedirect:'/users/teacher', failureRedirect:'/login',failureFlash: true}),
function(req, res) {
    res.redirect('/');
});

我的序列化和反序列化是:

passport.serializeUser(function(user, done) {
    if(Student.findOne({username: user.username}).length != 0) {
        done(null, user.id);
    } else if(Teacher.findOne({username: user.username}).length != 0) {
        done(null, user.id);
    }
});

passport.deserializeUser(function(id, done) {
    if(Student.getStudentById(id)){
        Student.getTeacherById(id, function(err, user) {
            done(err, user);
        });
    } else {
        Teacher.getTeacherById(id, function(err, user) {
            done(err, user);
        });
    }
});

我知道我的序列化是错误的,这就是为什么我无法让它工作的原因。当我尝试只使用一种类型的用户并且我在护照文件中找到更简单的序列化时,我的登录工作正常。我是节点和护照的新手,所以任何帮助都将受到高度赞赏。

1 个答案:

答案 0 :(得分:0)

我相信您的序列化不起作用,因为查找教师/学生的查询实际上是异步的,您将其视为同步。

passport.serializeUser(function(user, done) {
    Student.findOne( { username: user.username }, function( err, student ) {
         if ( student ) {
              // user is student
              done( null, user.id );
         } else {
              Teacher.findOne( { username: user.username }, function( err, teacher ) {
                   if ( teacher ) { 
                        // user is teacher
                        done( null, user.id );
                   }
              } );
         }
    } )
} );

这应该有用,虽然我不确定你为什么要查找用户类型。你可以这样做:

passport.serializeUser(function(user, done) {
     done(null, user.id);
} );