如何用passportjs实现两种策略

时间:2013-07-30 18:26:05

标签: node.js express passport.js

我的node / express app中有两个模型:

  1. 用户模型(简单用户通过身份验证)
  2. 经理模型(具有不同权限和不同字段的用户)
  3. 我想用护照来验证它们:

    1. 用户与一对:用户名/密码
    2. 经理与情侣:电子邮件/密码
    3. 我正确地为User模型实现了PassportJS,但现在我尝试对Manager模型执行相同操作。

      exports.postlogin = function(req, res, next) {
          passport.authenticate('user', function(err, user, info) {
              if (err) { return next(err) }
              if (!user) {
                  req.session.messages =  [info.message];
                  return res.redirect('/login')
              }
              req.logIn(user, function(err) {
                  if (err) { return next(err); }
                  return res.redirect('/');
              });
          })(req, res, next);
      };
      
      exports.postlogin = function(req, res, next) {
          passport.authenticate('manager', function(err, manager, info) {
              if (err) { return next(err) }
              if (!manager) {
                  req.session.messages =  [info.message];
                  return res.redirect('/manager_signup')
              }
              req.logIn(manager, function(err) {
                  if (err) { return next(err); }
                  return res.redirect('/');
              });
          })(req, res, next);
      };
      

      这两个策略:

      passport.use('user', new LocalStrategy(function(username, password, done) {
          UserModel.findOne({ username: username }, function(err, user) {
              if (err) { return done(err); }
              if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
              user.comparePassword(password, function(err, isMatch) {
                  if (err) return done(err);
                  if(isMatch) {
                      return done(null, user);
                  } else {
                      return done(null, false, { message: 'Invalid password' });
                  }
              });
          });
      }));
      
      passport.use('manager', new LocalStrategy({usernameField: 'manager_signin_email', passwordField: 'manager_signin_password'},function(manager_signin_email, manager_signin_password, done) {
          ManagerModel.findOne({ email: manager_signin_email }, function(err, manager) {
              if (err) { return done(err); }
              if (!manager) { return done(null, false, { message: 'Unknown manager ' + manager_signin_email }); }
              manager.comparePassword(manager_signin_password, function(err, isMatch) {
                  if (err) return done(err);
                  if(isMatch) {
                      console.log('Manager login OK : ' + manager_signin_email);
                      return done(null, manager);
                  } else {
                      return done(null, false, { message: 'Invalid password' });
                  }
              });
          });
      }));
      

      问题在于序列化/反序列化。 对于用户我有这个:

      passport.serializeUser(function(user, done) {
          done(null, user.id);
      });
      
      passport.deserializeUser(function(id, done) {
          UserModel.findById(id, function (err, user) {
              done(err, user);
          });
      });
      

      但我不知道如何为Manager模型做。

3 个答案:

答案 0 :(得分:1)

序列化时你可能会做这样的事情:

if (isUser(user)) {
    // serialize user
    done(null, "user_"+user.id );
  } else if (isManager(user)) {
    // serialize manager
    done(null, "manager_"+user.id );

  }

然后在反序列化时检查前缀。

答案 1 :(得分:0)

我认为你想要的是一个未解决的问题(https://github.com/jaredhanson/passport/issues/148)。

或者,您可以更改序列化方法以包含信息,如果它的用户或管理员不仅是用户ID,还是反序列化时读取该信息并从适当的模型加载用户/管理器。

答案 2 :(得分:0)

如果有人还在磕磕绊绊。您可以检查要序列化的对象的类型。请注意,对象的所有内容都归纳为一个PrincipleInfo对象。

function PrincipleInfo(principleId, principleType, details) {
    this.principleId = principleId;
    this.principleType = principleType;
    this.details = details;
}

passport.serializeUser(function (userObjectThing, done) {
    //userObjectThing could be a User or a Sponsor
    var principleType = "user";
    var userPrototype =  Object.getPrototypeOf(userObjectThing);
    if (userPrototype === User.prototype) {
        principleType = "user";
    } else if (userPrototype === Sponsor.prototype) {
        principleType = "sponsor";
    } else if (userPrototype === Admin.prototype) {
        principleType = "admin";
    }

    var principleInfo = new PrincipleInfo(userObjectThing.id, principleType, '');
    done(null,principleInfo);
});

    passport.deserializeUser(function (principleInfo, done) {

        if (principleInfo.principleType == 'user') {
            User.findOne({
                _id: principleInfo.principleId
            }, '-salt -hashedPassword', function (err, user) { // don't ever give out the password or salt
                done(err, user);
            });
        } else if (principleInfo.principleType == 'sponsor') {
            Sponsor.findOne({
                _id: principleInfo.principleId
            }, '-salt -hashedPassword', function (err, user) { // don't ever give out the password or salt
                done(err, user);
            });
        } else if (principleInfo.principleType == 'admin') {
            Admin.findOne({
                _id: principleInfo.principleId
            }, '-salt -hashedPassword', function (err, user) { // don't ever give out the password or salt
                done(err, user);
            });
        }

    });