Javascript 包含passport local注册电子邮件的输入字段是否必须具有属性';name=用户名';?

Javascript 包含passport local注册电子邮件的输入字段是否必须具有属性';name=用户名';?,javascript,node.js,express,passport.js,passport-local,Javascript,Node.js,Express,Passport.js,Passport Local,我为登录和注册用户设置了本地passport策略,我认为当前用户流的工作方式是用户访问注册页面,输入他们的电子邮件地址和密码,并可以在登录视图中使用完全相同的凭据登录。没什么特别的 我注意到,当我试图将输入字段的单行名称属性从“username”更改为类似“email”的内容以使其更具可读性时,代码会随着消息“Invalid user credentials”通过connect flash传播而中断。我见过的每一个概念证明都有输入信息是“用户名”,但当我改变这一行并输入一封不同的新电子邮件时,注

我为登录和注册用户设置了本地passport策略,我认为当前用户流的工作方式是用户访问注册页面,输入他们的电子邮件地址和密码,并可以在登录视图中使用完全相同的凭据登录。没什么特别的

我注意到,当我试图将输入字段的单行名称属性从“username”更改为类似“email”的内容以使其更具可读性时,代码会随着消息“Invalid user credentials”通过connect flash传播而中断。我见过的每一个概念证明都有输入信息是“用户名”,但当我改变这一行并输入一封不同的新电子邮件时,注册就不再有效了

以下是有争议的观点:

视图/signup.ejs
passport.js是否绝对要求注册策略的注册视图中的属性必须是用户名?这让我觉得不可思议。我想再次强调一个事实,我对现有功能注册流程所做的唯一更改就是将属性改为“email”,而不是“username”。

尽管类似的问题已经被问了好几次,在PassportJS使身份验证变得简单的背景下,他们没有一个真正好的答案,因此我们不能期望实现它的人深入研究它的代码

Passport local是大多数人在使用PassportJS时使用的策略。它通常需要用户名和电子邮件的值,如上所述

如果您进入
node\u modules//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;
    }
因此,基本上,它会检查您是否正确地传入了回调,并检查您是否传入了options对象。然后检查此选项对象以查看配置,它通过使用| |符号短路来执行此操作。因此,如果您不传入任何配置,它将默认为用户名和密码参数

因此,在本地配置中传递如下信息——在本例中,我将用户名替换为电子邮件

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{......
最后,进入您的模型或数据库模式,确保适当地更改列以匹配

额外信息: “为什么我们需要配置PassportJS?”(回答时,我也遇到了同样的问题)

答案是您需要根据数据库需要对其进行配置;您可能正在使用MySQL、MongoDB或其他数据库,每个PassportJS实现都必须以某种方式适应该数据库。以下是PassportJS在没有用户定制的情况下无法自行解决的问题

  • 我需要使用ORM吗
  • 我需要显示什么类型的错误消息
  • 我还需要接受哪些字段
TL;DR
按照passport本地创建者的意图,通过更改预期参数,将选项对象传递给您的新本地策略配置。

您需要告诉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;

今天早上我碰巧看到你的答案。我对你得到“正确答案”并不感到惊讶,但我对没有评论感到惊讶。我只是想说谢谢你这么详细的回答。@OmisNomis我感谢你的反馈,希望能对你有所帮助!
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;