Я пытаюсь использовать несколько стратегий LOCAL с помощью PassportJS. Я не пытаюсь использовать локальные, facebook и gmail и т.д. У меня есть два набора пользователей, которые хранятся в отдельных объектах, и я хочу использовать локальную стратегию для аутентификации обоих. Как бы то ни было, я не могу использовать одну и ту же локальную стратегию для обоих, потому что у них есть разные свойства объекта, которые требуют, чтобы я запрашивал разные объекты. Есть какой-либо способ сделать это? ИЛИ любые предложения по этому поводу будут очень признательны.
Используйте несколько локальных стратегий в PassportJS
Ответ 1
Я не думаю, что это возможно, потому что, насколько я вижу, вам нужен какой-то метод "передачи" запроса во вторую стратегию, когда первый не удается, и я не считаю, что это возможно.
Но вы можете использовать одну локальную стратегию и просто попытаться аутентифицировать входящие данные с помощью обоих методов.
В качестве простого примера (используя Mongoose в качестве примера базы данных):
passport.use(new LocalStrategy(function(username, password, done) {
Model1.findOne({ username : username }, function(err, user) {
// first method succeeded?
if (!err && user && passwordMatches(...)) {
return done(null, user);
}
// no, try second method:
Model2.findOne({ name : username }, function(err, user) {
// second method succeeded?
if (! err && user && passwordMatches(...)) {
return done(null, user);
}
// fail!
done(new Error('invalid user or password'));
});
});
}));
Для сериализации/десериализации вам может потребоваться сохранить некоторое свойство в объекте user
, которое вы передаете в done
, чтобы указать, какая модель требуется для десериализации пользователя.
Ответ 2
Вы можете называть свои локальные стратегии, чтобы их разделить.
// use two LocalStrategies, registered under user and sponsor names
// add other strategies for more authentication flexibility
passport.use('user-local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password' // this is the virtual field on the model
},
function(email, password, done) {
User.findOne({
email: email
}, function(err, user) {
if (err) return done(err);
if (!user) {
return done(null, false, {
message: 'This email is not registered.'
});
}
if (!user.authenticate(password)) {
return done(null, false, {
message: 'This password is not correct.'
});
}
return done(null, user);
});
}
));
// add other strategies for more authentication flexibility
passport.use('sponsor-local', new LocalStrategy({
usernameField: 'username',
passwordField: 'password' // this is the virtual field on the model
},
function(username, password, done) {
Sponsor.findOne({
'primaryContact.username': username
}, function(err, sponsor) {
if (err) return done(err);
if (!sponsor) {
return done(null, false, {
message: 'This email/username is not registered.'
});
}
if (!sponsor.authenticate(password)) {
return done(null, false, {
message: 'This password is not correct.'
});
}
return done(null, sponsor);
});
}
));
Более поздний код контроллера относится к ним по имени.
/**
* User Login
*/
exports.loginUser = function (req, res, next) {
passport.authenticate('local-user', function(err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
req.logIn(user, function(err) {
if (err) return res.send(err);
res.json(req.user.userInfo);
});
})(req, res, next);
};
/**
* Sponsor Login
*/
exports.loginSponsor = function (req, res, next) {
passport.authenticate('local-sponsor', function(err, sponsor, info) {
var error = err || info;
if (error) return res.json(401, error);
req.logIn(sponsor, function(err) {
if (err) return res.send(err);
res.json(req.sponsor.profile);
});
})(req, res, next);
};
Позже, когда придет время сериализовать пользователя, вы можете сделать что-то вроде этого.
// serialize
passport.serializeUser(function(user, done) {
if (isUser(user)) {
// serialize user
} else if (isSponsor(user)) {
// serialize company
}
});