Node.js 和 Passport 对象没有方法 validPassword

Posted

技术标签:

【中文标题】Node.js 和 Passport 对象没有方法 validPassword【英文标题】:Node.js and Passport Object has no method validPassword 【发布时间】:2012-11-13 22:36:49 【问题描述】:

我正在使用 Node.js + Express + Passport 创建一个简单的身份验证(本地)

到目前为止,当输入错误的用户名或密码时,用户会被重定向到错误页面

但是当用户输入正确的用户名和密码时,我得到了这个错误

node_modules\mongoose\lib\utils.js:435
    throw err;
          ^
TypeError: Object  _id: 50b347decfd61ab9e9e6768f,
username: 'saleh',
password: '123456'  has no method 'validPassword'

我不确定那里出了什么问题

app.js(我删除了不必要的代码):

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

  app.configure(function()
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
);



var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'authTest');

var authSchema = mongoose.Schema( 
  username: 'string',
  password: 'string'
);

var User = db.model('users', authSchema);


passport.use(new LocalStrategy(
  function(username, password, done) 
    User.findOne( username: username , function (err, user) 
      if (err)  return done(err); 
      if (!user) 
        return done(null, false,  message: 'Incorrect username.' );
      
      if (!user.validPassword(password)) 
        return done(null, false,  message: 'Incorrect password.' );
      
      return done(null, user);
    );
  
));



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

passport.deserializeUser(function(id, done) 
  User.findById(id, function(err, user) 
    done(err, user);
  );
);




app.post('/login',
  passport.authenticate('local',  successRedirect: '/',
                                   failureRedirect: '/login/error',

                                  )
);

现在在 routes/login.js 中

var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'authTest');

var authSchema = mongoose.Schema( 
    username: 'string',
    password: 'string'
);

var User = db.model('users', authSchema);

exports.index = function(req, res)
User.find(function (err, list) 
        res.render('login',  title: 'Usernames and Passwords', users: list,msg:"");
    );
;

感谢您的宝贵时间。

【问题讨论】:

【参考方案1】:

你正在使用

if (!user.validPassword(password)) 
    return done(null, false,  message: 'Incorrect password.' );

但是你还没有定义validPassword 方法。将其附加到您的架构:

var authSchema = mongoose.Schema( 
    username: 'string',
    password: 'string'
);
authSchema.methods.validPassword = function( pwd ) 
    // EXAMPLE CODE!
    return ( this.password === pwd );
;

EDIT 您还错误地定义了架构。应该是:

var authSchema = mongoose.Schema( 
    username: String,
    password: String
);

注意usernamepassword 都应该是String 类型的对象,而不是字符串"string",如果你明白我的意思的话。 :)

【讨论】:

如果可以的话,还有一个问题.. 你能推荐一本书或任何资源来更好地学习 Node.js 吗? @MuhammadSaleh 我不知道任何 Node.JS 书籍。我通过不断的谷歌搜索学到了一切。从Node.JS main page 上的教程开始。然后只是谷歌。 *** 也是一个很好的知识来源。我就是这样学会的。 不过,这是用于 Passport 的。不应该已经有了哈希密码和检查密码的功能吗?【参考方案2】:

看起来你从 passportjs 网站复制了示例,Jared 没有提及如何实现它。

在护照 js github 页面上,他有另一个(更简单的)示例;他完全删除了 validPassword 方法(第 18 行):

Example

if (user.password != password)  return cb(null, false); 

这就是我基于它的应用程序(使用加密)的基础。

【讨论】:

谢谢我真的需要一个更简单的例子,我还联系了 Jared 以制作更好的文档:)【参考方案3】:

我也是一个菜鸟,我花了一整天的时间才弄清楚这个。我使用了 Jared 的另一个示例应用程序的历史记录,以及来自这里的人们的一些加密建议。

首先我做了一个方法来生成一个盐(一个大的随机数,被字符串化),使用盐和用户的密码来创建一个哈希(在 nodejs 'crypto' 模块的帮助下),最后存储每次 mongoose 保存新帐户之前的 salt 和 hash。

//make hash
userSchema.pre('save', function(next) 
    var user = this;
    if(!user.isModified('password')) return next();
    var rand = (Math.floor(Math.random() * 1000000000)).toString(36);
    var hash = crypto.createHash('md5').update(user.password + rand).digest("hex");
    user.password = hash;
    user.salt = rand;
    next();
);

为了验证,我只需输入输入的密码(在登录时)并尝试使用 salt 再次生成相同的哈希值。然后我将存储的哈希值与新的哈希值进行比较,并相应地返回 true 或 false。

 // Password verification
    userSchema.methods.validPassword = function(password) 
      var testhash = crypto.createHash('md5').update(password + this.salt).digest("hex");
      if(testhash === this.password) 
        return true;
       else 
        return false;
      
    

【讨论】:

当你意识到这是一岁的那一刻。 没关系 :) 感谢贡献 这个答案可能应该更新,因为使用 md5 和 Math.random 不安全。

以上是关于Node.js 和 Passport 对象没有方法 validPassword的主要内容,如果未能解决你的问题,请参考以下文章

为移动应用程序进行 facebook 登录的正确方法是啥(使用 node.js/passport.js 服务器)

使用 passport.js 和 express.js (node.js) 制作安全的 oauth API

测试受保护的 api 调用、mocha、supertest、node js、passport

node.js试图让护照和ExtraxtJwt工作

在带有 React.js 前端的 Node.js 上使用 Passport.js 进行身份验证

Passport Node.js CORS 错误