包含用于在 passport-local 中注册的电子邮件的输入字段是否必须具有属性 'name = username'?
Does input field containing email for signup in passport-local have to have attribute 'name = username'?
我设置了本地通行证策略来登录和注册用户,我当前用户流程的工作方式是用户访问注册页面,输入他们的电子邮件地址和密码,然后可以使用完全相同的凭据登录在登录视图中。没有什么花哨。
我注意到,当我尝试将输入字段的单行名称属性从 'username' 更改为类似 'email' 以使其更具可读性时,代码中断消息 "Invalid user credentials" 通过 connect-flash 传播。我见过的每一个概念证明都有输入信息 'username',但是当我更改那一行并输入一个不同的新电子邮件时,注册不再有效。
这里是有问题的观点:
views/signup.ejs
<h1><span class="fa fa-sign-in"></span> Signup</h1>
<!-- show any messages that come back with authentication -->
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
<!-- LOGIN FORM -->
<form action="/users/signup" method="post">
<div class="form-group">
<label>Email</label>
<!-- the line directly below works -->
<input type="text" class="form-control" name="username">
<!-- but this line immediately below does not work! -->
<!-- <input type="text" class="form-control" name="email"> -->
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-warning btn-lg">Signup</button>
</form>
这是我的本地注册策略:
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function(user) {
done(null, user);
})
.catch(function(err){
done(err, null);
});
});
passport.use('local-signup', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true },
function(req, email, password, done){
if(req.session.user && req.session){
done(null, false, {message: 'User is already logged in, signup illegal'});
}
else{
db.User.findOne({ where: {email : email }})
.then(function(user) {
if(user !== null) {
done(null, false, {message: 'User already exists'});
}
else{
//create user yada yada
}
})
.catch(function(err){
return done(null, false, {message: err});
});
}
}
));
passport.js 是否绝对要求注册视图中注册策略的属性必须是用户名?这让我觉得非常奇怪。再次强调,我对现有功能注册流程所做的唯一更改实际上是将属性更改为 'email' 而不是 'username'.
虽然类似的问题已经被问过几次,但在 PassportJS 使身份验证变得简单的背景下,他们没有一个很好的答案,所以我们不能指望实施它的人深入研究它代码。
Passport-local 是大多数人在使用 PassportJS 时会使用的策略。如上所述,它通常需要用户名和电子邮件的值。
如果您进入 node_modules/<path to passport-local>/strategy.js
,您会找到更多关于如何实现它的文档。
`Strategy` constructor.
The local authentication strategy authenticates requests based on the
credentials submitted through an HTML-based login form.
Applications must supply a `verify` callback which accepts `username` and
`password` credentials, and then calls the `done` callback supplying a
`user`, which should be set to `false` if the credentials are not valid.
If an exception occured, `err` should be set.
Optionally, `options` can be used to change the fields in which the
credentials are found.
Options:
- `usernameField` field name where the username is found, defaults to _username_
- `passwordField` field name where the password is found, defaults to _password_
- `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`)
下面提供的 Jared Hanson 的示例坦率地说是不充分的,因为它甚至没有实现任何这些功能,因此,我省略了它,但是如果您查看实际的 Strategy 构造函数的代码,清晰多了。
function Strategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = {};
}
if (!verify) { throw new TypeError('LocalStrategy requires a verify callback'); }
this._usernameField = options.usernameField || 'username';
this._passwordField = options.passwordField || 'password';
passport.Strategy.call(this);
this.name = 'local';
this._verify = verify;
this._passReqToCallback = options.passReqToCallback;
}
所以,基本上,它会检查您是否正确地传入了回调,并检查您是否传入了选项对象。然后检查此选项对象以查看配置,它通过与 || 短路来实现。象征。因此,如果您不传入任何配置,它将默认为 username 和 password 参数。
因此,按如下方式在您的本地配置中传递 -- 在本示例中,我将用户名换成电子邮件。
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done){
if(req.session.user && req.session){
done(null, false, {message: 'User is already logged in, signup illegal'});
}
else{......
最后,进入您的模型或数据库模式并确保适当地更改列以匹配。
额外信息:
"Why do we need to configure PassportJS?"(回答是因为我也遇到了同样的问题)
答案是您需要根据您的数据库需求对其进行配置;您可能正在使用 MySQL、MongoDB 或其他一些数据库,并且每个 PassportJS 实现都必须以某种方式适合该数据库。以下是 PassportJS 在没有用户自定义的情况下无法自行解决的问题。
- 我需要使用 ORM 吗?
- 我需要显示什么样的错误信息?
- 我还需要接受哪些其他字段?
TL;DR
按照本地护照创建者的预期更改预期参数,将选项对象传递给您的新本地策略配置。
您需要告诉 Passport 您将使用电子邮件字段作为用户名。
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function(user) {
done(null, user);
})
.catch(function(err){
done(err, null);
});
});
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
if(req.session.user && req.session){
done(null, false, {message: 'User is already logged in, signup illegal'});
}
else{
db.User.findOne({ where: {email : email }})
.then(function(user) {
if(user !== null) {
done(null, false, {message: 'User already exists'});
}
else{
//create user yada yada
}
})
.catch(function(err){
return done(null, false, {message: err});
});
}
}
));
您可以通过从正文中获取字段来将用户名与电子邮件结合使用。
req.body.username;
我设置了本地通行证策略来登录和注册用户,我当前用户流程的工作方式是用户访问注册页面,输入他们的电子邮件地址和密码,然后可以使用完全相同的凭据登录在登录视图中。没有什么花哨。
我注意到,当我尝试将输入字段的单行名称属性从 'username' 更改为类似 'email' 以使其更具可读性时,代码中断消息 "Invalid user credentials" 通过 connect-flash 传播。我见过的每一个概念证明都有输入信息 'username',但是当我更改那一行并输入一个不同的新电子邮件时,注册不再有效。
这里是有问题的观点:
views/signup.ejs
<h1><span class="fa fa-sign-in"></span> Signup</h1>
<!-- show any messages that come back with authentication -->
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
<!-- LOGIN FORM -->
<form action="/users/signup" method="post">
<div class="form-group">
<label>Email</label>
<!-- the line directly below works -->
<input type="text" class="form-control" name="username">
<!-- but this line immediately below does not work! -->
<!-- <input type="text" class="form-control" name="email"> -->
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-warning btn-lg">Signup</button>
</form>
这是我的本地注册策略:
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function(user) {
done(null, user);
})
.catch(function(err){
done(err, null);
});
});
passport.use('local-signup', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true },
function(req, email, password, done){
if(req.session.user && req.session){
done(null, false, {message: 'User is already logged in, signup illegal'});
}
else{
db.User.findOne({ where: {email : email }})
.then(function(user) {
if(user !== null) {
done(null, false, {message: 'User already exists'});
}
else{
//create user yada yada
}
})
.catch(function(err){
return done(null, false, {message: err});
});
}
}
));
passport.js 是否绝对要求注册视图中注册策略的属性必须是用户名?这让我觉得非常奇怪。再次强调,我对现有功能注册流程所做的唯一更改实际上是将属性更改为 'email' 而不是 'username'.
虽然类似的问题已经被问过几次,但在 PassportJS 使身份验证变得简单的背景下,他们没有一个很好的答案,所以我们不能指望实施它的人深入研究它代码。
Passport-local 是大多数人在使用 PassportJS 时会使用的策略。如上所述,它通常需要用户名和电子邮件的值。
如果您进入 node_modules/<path to passport-local>/strategy.js
,您会找到更多关于如何实现它的文档。
`Strategy` constructor.
The local authentication strategy authenticates requests based on the
credentials submitted through an HTML-based login form.
Applications must supply a `verify` callback which accepts `username` and
`password` credentials, and then calls the `done` callback supplying a
`user`, which should be set to `false` if the credentials are not valid.
If an exception occured, `err` should be set.
Optionally, `options` can be used to change the fields in which the
credentials are found.
Options:
- `usernameField` field name where the username is found, defaults to _username_
- `passwordField` field name where the password is found, defaults to _password_
- `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`)
下面提供的 Jared Hanson 的示例坦率地说是不充分的,因为它甚至没有实现任何这些功能,因此,我省略了它,但是如果您查看实际的 Strategy 构造函数的代码,清晰多了。
function Strategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = {};
}
if (!verify) { throw new TypeError('LocalStrategy requires a verify callback'); }
this._usernameField = options.usernameField || 'username';
this._passwordField = options.passwordField || 'password';
passport.Strategy.call(this);
this.name = 'local';
this._verify = verify;
this._passReqToCallback = options.passReqToCallback;
}
所以,基本上,它会检查您是否正确地传入了回调,并检查您是否传入了选项对象。然后检查此选项对象以查看配置,它通过与 || 短路来实现。象征。因此,如果您不传入任何配置,它将默认为 username 和 password 参数。
因此,按如下方式在您的本地配置中传递 -- 在本示例中,我将用户名换成电子邮件。
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done){
if(req.session.user && req.session){
done(null, false, {message: 'User is already logged in, signup illegal'});
}
else{......
最后,进入您的模型或数据库模式并确保适当地更改列以匹配。
额外信息: "Why do we need to configure PassportJS?"(回答是因为我也遇到了同样的问题)
答案是您需要根据您的数据库需求对其进行配置;您可能正在使用 MySQL、MongoDB 或其他一些数据库,并且每个 PassportJS 实现都必须以某种方式适合该数据库。以下是 PassportJS 在没有用户自定义的情况下无法自行解决的问题。
- 我需要使用 ORM 吗?
- 我需要显示什么样的错误信息?
- 我还需要接受哪些其他字段?
TL;DR 按照本地护照创建者的预期更改预期参数,将选项对象传递给您的新本地策略配置。
您需要告诉 Passport 您将使用电子邮件字段作为用户名。
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function(user) {
done(null, user);
})
.catch(function(err){
done(err, null);
});
});
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
if(req.session.user && req.session){
done(null, false, {message: 'User is already logged in, signup illegal'});
}
else{
db.User.findOne({ where: {email : email }})
.then(function(user) {
if(user !== null) {
done(null, false, {message: 'User already exists'});
}
else{
//create user yada yada
}
})
.catch(function(err){
return done(null, false, {message: err});
});
}
}
));
您可以通过从正文中获取字段来将用户名与电子邮件结合使用。
req.body.username;