javascript - Passport.js:LocalStrategy 如何访问用户信息?
问题描述
我已经阅读了几篇文章,解释了护照身份验证的流程并理解了大部分概念。但是,仍有一些模糊的地方需要解释,以便我可以一劳永逸地了解 Passport。
让我们看看这个实现用户注册的简单示例:
护照.js
passport.use(
'register',
new LocalStrategy(
{
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true,
session: false,
},
(req, username, password, done) => {
// TODO:Why is req.body.email is used and not req.body.username
// And how are these values passed to register in the first place?
console.log(username);
console.log(req.body.email);
try {
User.findOne({
where: {
[Op.or]: [
{
username,
},
{ email: req.body.email },
],
},
}).then(user => {
if (user != null) {
console.log('username or email already taken');
return done(null, false, {
message: 'username or email already taken',
});
}
/**
* on register the user’s password is hashed and salted with the encryption package bcrypt
*
*/
bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
User.create({
username,
password: hashedPassword,
email: req.body.email,
}).then(user => {
console.log('user created');
return done(null, user);
});
});
});
} catch (err) {
//In case of an Error interacting with our database, we need to invoke done(err)
//Calling done will make the flow jump back into passport.authenticate.
//It's passed the error, user and additional info object (if defined).
return done(err);
}
},
),
);
注册用户.js:
app.post('/registerUser', (req, res, next) => {
//Calling done will make the flow jump back into passport.authenticate.
//It's passed the error, user and additional info object (if defined).
passport.authenticate('register', (err, user, info) => {
if (err) {
console.error(err);
}
if (info !== undefined) {
console.error(info.message);
res.status(403).send(info.message);
} else {
// eslint-disable-next-line no-unused-vars
req.logIn(user, error => {
console.log(user);
const data = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
username: user.username,
};
console.log(data);
User.findOne({
where: {
username: data.username,
},
}).then(user => {
console.log(user);
user
.update({
first_name: data.first_name,
last_name: data.last_name,
email: data.email,
})
.then(() => {
console.log('user created in db');
res.status(200).send({ message: 'user created' });
});
});
});
}
})(req, res, next);
});
问题 1:知道已以这种方式调用 Passport.authenticate ,我看不到LocalStrategy内部的代码如何访问用户信息:
app.post('/registerUser', (req, res, next) => {
passport.authenticate('register', (err, user, info) => {
那么 **regiser LocalStrategy ** 中的代码如何访问用户名、电子邮件和密码:
(req, username, password, done) => {
console.log(username);
console.log(req.body.email);
问题2:为什么LocalStrategy中的用户名直接称为用户名 (密码相同)而电子邮件由req.body.email调用?
console.log(username);
console.log(req.body.email);
和这里:
User.create({
username,
password: hashedPassword,
email: req.body.email,
})
问题3:如果注册LocalStrategy中已经创建了用户,为什么还要在请求回调中更新用户信息:
注册用户.js
.update({
first_name: data.first_name,
last_name: data.last_name,
email: data.email,
})
护照.js
User.create({
username,
password: hashedPassword,
email: req.body.email,
})
编辑 1
问题 4:(req, res, next) 的作用是什么;在POST回调结束时?
解决方案
问题 1&2:答案在传递的对象中LocalStrategy:
{
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true,
session: false,
}
属性passReqToCallback,req将作为第一个参数传递给验证回调:
(req, username, password, done) => {}
但是,仍然不清楚的是用户名和密码是如何传递给这个函数的。为什么在这个对象中以这种方式定义它们:
usernameField: 'username',
passwordField: 'password',
不应该像电子邮件一样通过 req.body.username 访问它们:
User.findOne({
where: {
[Op.or]: [
{
username,
},
{ email: req.body.email },
],
},
问题3:这是我找到的解释:
我也可以将这些额外的数据传递给中间件,但我希望 Passport 只处理身份验证,而不是用户创建。模块化,记住。
另外,如果将身份验证拆分为一个单独的服务,其中包含一个仅包含加密用户名和密码的单独数据库,那么这样做会更容易,然后使用用户名或 ID 来查找和更新此文件中的相应用户记录注册服务。