我正在尝试使用PassportJS的多种LOCAL策略。我不是想使用本地,脸谱和Gmail等。 我有两组用户存储在不同的对象中,我想使用本地策略对两者进行身份验证。就目前而言,我不能对两者使用相同的本地策略,因为它们具有不同的对象属性,这使我可以查询不同的对象。有没有办法做到这一点?或者对此有任何建议将不胜感激。
答案 0 :(得分:137)
您可以命名您的本地策略以将它们分开。
// 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('user-local', 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('sponsor-local', 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
}
});
答案 1 :(得分:7)
我认为这是不可能的,因为据我所知,当第一个策略失败时,你需要一些方法将请求“转交”给第二个策略,我不相信这是可能的。
但您可以使用一种本地策略,并尝试使用这两种方法验证传入数据。
作为一个简单的例子(使用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
的{{1}}对象中存储一些属性,以表示反序列化用户所需的模型。
答案 2 :(得分:1)
您可以将类似的方法用于多种本地策略
passport.use('local.one', myLocalStrategy1);
passport.use('local.two', myLocalStrategy2);
passport.use('local.three', myLocalStrategy3);
...
app.get('/login/s1', passport.authenticate('local.one');
app.get('/login/s2', passport.authenticate('local.two');
app.get('/login/s3', passport.authenticate('local.three');
答案 3 :(得分:0)
1)在用户注册表中保存默认角色:数据库中的“客户” 2)在管理员注册表中保存默认角色:'admin' in database
[Note- If you use mongodb as a database in registration schema make-
role:{
type: String,
default: 'customer' or 'admin' //Manage respectively
},
Important- 'This uses cookie for session login'
'You can do this on your own way :)']
passport.use('user-local',
new LocalStrategy({ usernameField: 'phone', passwordField: 'password' },
(phone, password, done) => {
// Match user
User.findOne({
phone: phone
}).then(user => {
if (!user) {
return done(null, false, { message: 'The phone not registered' });
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
})
.catch(err => console.log(err));
})
);
passport.use('admin-local',
new LocalStrategy({ usernameField: 'phone', passwordField: 'password' },
(phone, password, done) => {
// Match user
Admin.findOne({
phone: phone
}).then(user => {
if (!user) {
return done(null, false, { message: 'The phone not registered' });
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
})
.catch(err => console.log(err));
})
);
passport.serializeUser((user, done) => {
done(null, { _id: user.id, role: user.role });
});
passport.deserializeUser((login, done) => {
if (login.role === 'customer') {
User.findById(login, function (err, user) {
if (user)
done(null, user);
else
done(err, { message: 'User not found' })
});
}
else if (login.role === 'admin') {
Admin.findById(login, (err, admin) => {
if (admin)
done(null, admin);
else
done(err, { message: 'Admin not found' })
});
}
else {
done({ message: 'No entity found' }, null);
}
});