Javascript Node.js Passport策略使用电子邮件或用户名登录

Javascript Node.js Passport策略使用电子邮件或用户名登录,javascript,node.js,passport.js,Javascript,Node.js,Passport.js,我在node.js应用程序上使用Passport,目前使用用户名登录 在我的用户注册页面上,我允许用户注册他们的唯一用户名和电子邮件 我想要一个带有“使用用户名/电子邮件登录:\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 脚本可以检测字段中是否有“@”,并查找电子邮件而不是用户名 我试了几个小时都没有用 这是我的护照 var mongoose = require('mongoose') var LocalStrategy = require('pa

我在node.js应用程序上使用Passport,目前使用用户名登录

在我的用户注册页面上,我允许用户注册他们的唯一用户名和电子邮件

我想要一个带有“使用用户名/电子邮件登录:\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

脚本可以检测字段中是否有“@”,并查找电子邮件而不是用户名

我试了几个小时都没有用

这是我的护照

var mongoose = require('mongoose')
var LocalStrategy = require('passport-local').Strategy

var User = mongoose.model('User');

module.exports = function(passport, config){

passport.serializeUser(function(user, done){
    done(null, user.id);
})

passport.deserializeUser(function(id, done) {
    User.findOne({ _id: id }, function (err, user) {
        done(err, user);
    });
});

passport.use(new LocalStrategy({
    usernameField: 'username',
    passwordField: 'password'
    }, function(username, password, done) {
    User.isValidUserPassword(username, password, done);
    }));
}
编辑:下面是请求的user.js

var mongoose = require('mongoose');
var hash = require('../util/hash.js');

UserSchema = mongoose.Schema({
username:  String,
email:      String,
salt:       String,
hash:       String
})

UserSchema.statics.signup = function(username, email, password, done){
var User = this;

hash(password, function(err, salt, hash){
    if(err) throw err;
    // if (err) return done(err);
    User.create({
        username : username,
        email: email,
        salt : salt,
        hash : hash
    }, function(err, user){
        if(err) throw err;
        // if (err) return done(err);
        done(null, user);
    });
});
}

UserSchema.statics.isValidUserPassword = function(username, password, done) {
this.findOne({username : username}, function(err, user){
    // if(err) throw err;
    if(err) return done(err);
    if(!user) return done(null, false, { message : 'Incorrect username.' });
    hash(password, user.salt, function(err, hash){
        if(err) return done(err);
        if(hash == user.hash) return done(null, user);
        done(null, false, {
            message : 'Incorrect password'
        });
    });
});
};

var User = mongoose.model("User", UserSchema);

module.exports = User;

好的,你的猫鼬模型中应该有这样的东西:

UserSchema.statics.isValidUserPassword = function(username, password, done) {
    var criteria = (username.indexOf('@') === -1) ? {username: username} : {email: username};
    this.findOne(criteria, function(err, user){
        // All the same...
    });
};

这是猫鼬的东西,而不是护照的东西,如果你能尝试一下,用布雷迪钦的答案^ ^:

var criteria = {$or: [{username: username}, {email: username}, {mobile: username}, {anything: username}]};
关键是通过mongodb的查询找到用户

通过这种方式,您可以进行任何查询以查找用户。

对于使用用户名或电子邮件登录,您还可以使用的findByUsername选项修改queryParameters

// add passport functions
// schema.plugin(passportLocalMongoose);
schema.plugin(passportLocalMongoose, {
    // allow sign in with username OR email
    findByUsername: function(model, queryParameters) {
        // start
        // // queryParameters => { '$or' : [ { 'username' : 'searchString' } ] }
        // iterate through queryParameters
        for( let param of queryParameters.$or ){
            // if there is a username
            if( typeof param == "object" && param.hasOwnProperty("username") ){
                // add it as an email parameter
                queryParameters.$or.push( { email : param.username } );
            }
        }
        // expected outcome
        // queryParameters => { '$or' : [ { 'username' : 'searchString' }, { 'email' : 'searchString' } ] }
        return model.findOne(queryParameters);
    }
});

很简单,你必须自己重新定义passport策略,就像下面的代码一样

用用户名序列化

passport.serializeUser(function(user, done) {
    done(null, user.username);});
passport.deserializeUser(function(username, done) {
User.findOne({username:username},function(err, user){
    done(err,user);
}); });
使用用户名反序列化

passport.serializeUser(function(user, done) {
    done(null, user.username);});
passport.deserializeUser(function(username, done) {
User.findOne({username:username},function(err, user){
    done(err,user);
}); });
护照策略

//passport strategy
passport.use(new LocalStrategy(function(username, password, done) {
        console.log(username.includes("@"));
      User.findOne((username.includes("@"))?{email:username}:{username:username}, function(err, user) {   
        if (err) {return done(err); }
        if (!user) {console.log("i am ERROR"); return done(null, false, { message: 'Incorrect username.' });}
        if (user.password===password) {return done(null, user); }
        return done(null, false);
      });
    }
  ));

注意:此处
user.password===password
表示数据库中的密码以明文形式存储。。您必须手动将密码插入数据库,例如
password:req.body.password
您还必须在添加或比较之前对用户自身进行加密和解密。

或者您只需制作一个中间件来处理类似情况:

const User = require("../models/user");
var middlewareObj = {};

middlewareObj.checkUsername = function (req, res, next) {
    if (req.body.username.indexOf('@') !== -1) {
        User.findOne({ email: req.body.username }, (err, foundUser) => {
            if (err || !foundUser) {
                req.flash('error', 'Please check your username or password');
                return res.redirect('/login');
            } else {
                req.body.username = foundUser.username;
                next();
            }
        });
    } else {
        next();
    }
}

module.exports = middlewareObj;
只需将其添加到登录路径:

app.post('/login', middleware.checkUsername, function (req, res, next) {
    //Login logic goes here
}

电子邮件/用户名检测部分在哪里?也许,在猫鼬模型中?如果能看一看,会很有帮助的。谢谢你的回复。我已经编辑了这篇文章,加入了user.js。非常感谢你,先生!你太棒了!好极了如果可能的话,这应该有数百万张选票@布雷迪钦