0

我的节点/快递应用程序中有两个模型:

  1. 用户模型(简单用户认证)
  2. 管理者模型(不同权限、不同字段的用户)

我想用护照来认证他们:

  1. 情侣用户:用户名/密码
  2. 经理与夫妇:电子邮件/密码

我为 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 模型做。

4

3 回答 3

1

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

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

  }

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

于 2014-04-08T21:37:45.920 回答
0

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

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

于 2013-07-30T19:09:15.657 回答
0

以防有人仍然绊倒这个。您可以检查您正在序列化的对象的类型。请注意,所有 by 对象都概括为 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);
            });
        }

    });
于 2014-06-20T21:58:20.457 回答