Javascript bcrypt密码与比较方法的比较结果总是错误的
首先,我知道同样的问题在我之前被问过很多次,但我在StackOverflow上发现的任何问题都找不到答案 我最近刚开始学习Javascript bcrypt密码与比较方法的比较结果总是错误的,javascript,mongodb,express,bcrypt,mongoose-schema,Javascript,Mongodb,Express,Bcrypt,Mongoose Schema,首先,我知道同样的问题在我之前被问过很多次,但我在StackOverflow上发现的任何问题都找不到答案 我最近刚开始学习express,第一次尝试用 javascript库(来自PHPworld)。我已经声明了一个MongoDB模型模式,其中包含一些准备工作和一个将输入的密码与 数据库中存储的哈希密码。除了comparePassword方法从未返回匹配的密码外,其他一切似乎都正常工作 我使用bcryptjs库进行密码散列和比较,使用passport库进行身份验证 用户模型(models/Use
express
,第一次尝试用
javascript库(来自PHP
world)。我已经声明了一个MongoDB
模型模式,其中包含一些准备工作和一个将输入的密码与
数据库中存储的哈希密码。除了comparePassword
方法从未返回匹配的密码外,其他一切似乎都正常工作
我使用bcryptjs
库进行密码散列和比较,使用passport
库进行身份验证
用户模型(models/User.js):
身份验证策略(config/passport.js):
最后是我的登录路径(routes/auth.js):
编辑:
如果我删除控制台.log中的输出:
bcrypt.compare(candidatePassword, user.password, function(err, isMatch) {
console.log(candidatePassword);
console.log(user.password);
console.log((candidatePassword === user.password) ? 'passwords match' : 'passwords dont match' );
return;
if (err) return cb(null, err);
cb(null, isMatch);
});
};
并尝试执行回调函数,我将得到以下错误:
cb(null, isMatch);
^
TypeError: undefined is not a function
at D:\project\backend\dist\models\user.js:51:9
at D:\project\node_modules\bcryptjs\dist\bcrypt.js:297:21
at D:\project\node_modules\bcryptjs\dist\bcrypt.js:1250:21
at Object.next [as _onImmediate] (D:\project\node_modules\bcryptjs\dist\bcrypt.js:1130:21)
at processImmediate [as _immediateCallback] (timers.js:354:15)
编辑2:
因此,我终于能够比较密码,并且能够console.log
密码是否匹配。我能够通过承诺实现这一点。现在我不确定如何将该承诺传递给passport
处理程序,以便它能够返回路由的用户结果
以下是comparePassword
方法:
userSchema.methods.comparePassword = function(candidatePassword) {
var user = this;
return new Promise(function(resolve,reject)
{
bcrypt.compare(candidatePassword, user.password, function (err, isMatch) {
// Prevent conflict btween err and isMatch
if (err)
reject(new Error("Error checking use password"));
else
console.log(isMatch === true ? 'passwords match' : 'passwords dont match');
return;
resolve(isMatch);
});
});
};
以及passport.js
:
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(username, password, done) {
User.findOne({ email: username }, function (err, user) {
if (err) { return done(err); }
// Return if user not found in database
user.comparePassword(password).then(function(isMatch) {
return isMatch === true ? user : null; // How to pass the user object to route??
}).catch(function (err) { // handle possible errors
return done(err);
})
});
}
));
我以为你只是在bcrypt比较中传递回调。确保将明文密码作为参数传递,并将其与db中的哈希密码进行比较
而不是这样做
if (!user.comparePassword(password)) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
}
为什么不这样做呢
user.comparePassword(function (err, match) {
if (err) throw err;
if (!match) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
} else {
// Password match
}
});
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailure'
})
);
app.get('/loginFailure', function(req, res, next) {
res.send('Failed to authenticate');
});
// Login success should return user object
app.get('/loginSuccess', function(req, res, next) {
res.send('Successfully authenticated');
});
在bcrypt compare方法中,更改回调参数,err必须是第一个,res必须是第二个
userSchema.methods.comparePassword = function(candidatePassword, cb) {
var user = this;
bcrypt.compare(candidatePassword, user.password, function(err, isMatch) {
console.log(candidatePassword);
console.log(user.password);
// You shouldn't compare the password directly like this. Let the method handle it and once the response is return (isMatch), pass it as callback param. Comment this line, you don't need it
//console.log((candidatePassword === user.password) ? 'passwords match' : 'passwords dont match' );
//return;
// Prevent conflict btween err and isMatch
if (err) return cb(err, null);
cb(null, isMatch);
});
};
编辑
当密码匹配并传递用户对象时,需要调用done
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(username, password, done) {
User.findOne({ email: username }, function (err, user) {
if (err) { return done(err); }
// Return if user not found in database
user.comparePassword(password).then(function(isMatch) {
if (isMatch) {
return done(null, user);
} else {
return done(null, false);
}
}).catch(function (err) { // handle possible errors
return done(err);
})
});
}
));
在中档软件中
我猜你的路线是这样的
user.comparePassword(function (err, match) {
if (err) throw err;
if (!match) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
} else {
// Password match
}
});
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailure'
})
);
app.get('/loginFailure', function(req, res, next) {
res.send('Failed to authenticate');
});
// Login success should return user object
app.get('/loginSuccess', function(req, res, next) {
res.send('Successfully authenticated');
});
我以为你只是在bcrypt比较中传递回调。确保将明文密码作为参数传递,并将其与db中的哈希密码进行比较
而不是这样做
if (!user.comparePassword(password)) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
}
为什么不这样做呢
user.comparePassword(function (err, match) {
if (err) throw err;
if (!match) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
} else {
// Password match
}
});
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailure'
})
);
app.get('/loginFailure', function(req, res, next) {
res.send('Failed to authenticate');
});
// Login success should return user object
app.get('/loginSuccess', function(req, res, next) {
res.send('Successfully authenticated');
});
在bcrypt compare方法中,更改回调参数,err必须是第一个,res必须是第二个
userSchema.methods.comparePassword = function(candidatePassword, cb) {
var user = this;
bcrypt.compare(candidatePassword, user.password, function(err, isMatch) {
console.log(candidatePassword);
console.log(user.password);
// You shouldn't compare the password directly like this. Let the method handle it and once the response is return (isMatch), pass it as callback param. Comment this line, you don't need it
//console.log((candidatePassword === user.password) ? 'passwords match' : 'passwords dont match' );
//return;
// Prevent conflict btween err and isMatch
if (err) return cb(err, null);
cb(null, isMatch);
});
};
编辑
当密码匹配并传递用户对象时,需要调用done
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(username, password, done) {
User.findOne({ email: username }, function (err, user) {
if (err) { return done(err); }
// Return if user not found in database
user.comparePassword(password).then(function(isMatch) {
if (isMatch) {
return done(null, user);
} else {
return done(null, false);
}
}).catch(function (err) { // handle possible errors
return done(err);
})
});
}
));
在中档软件中
我猜你的路线是这样的
user.comparePassword(function (err, match) {
if (err) throw err;
if (!match) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
} else {
// Password match
}
});
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailure'
})
);
app.get('/loginFailure', function(req, res, next) {
res.send('Failed to authenticate');
});
// Login success should return user object
app.get('/loginSuccess', function(req, res, next) {
res.send('Successfully authenticated');
});
我尝试了这个方法,但行为仍然与我的原始代码相同:如果我尝试控制台匹配,它将输出“密码不匹配”
,如果我删除返回
并尝试回调,我会得到一个错误:cb(null,isMatch);类型错误:未定义不是函数
Oh。我只是注意到您将return放在console.log之后。什么意思?是否要防止该错误。您不能像那样使用等价字符串直接比较它,它将不起作用。让bcrypt.compare处理它,然后尝试console.log(isMatch),这是您将得到的结果。该错误意味着cb未被识别为函数。您需要传递回调函数,正如我在上面的回答中所说的。请您再告诉我一点好吗?我对Javascript比较陌生,因为我主要使用PHP和类似的服务器端语言编写代码,对那些回调、承诺等有点困惑。哦,我明白了。回调和承诺的创建实际上是为了处理asncyrous。因此,nodejs是一种异步的特性,那么您就不能同时使用这两种方法。您可以选择使用回调或承诺。有很多简单的文档解释了回调和承诺的细节。我尝试了这一点,但行为仍然与我的原始代码相同:如果我尝试控制台匹配,它将输出“密码不匹配”
,如果我删除返回
并尝试回调,我会得到一个错误:cb(null,isMatch); 类型错误:未定义不是函数
Oh。我只是注意到您将return放在console.log之后。什么意思?是否要防止该错误。您不能像那样使用等价字符串直接比较它,它将不起作用。让bcrypt.compare处理它,然后尝试console.log(isMatch),这是您将得到的结果。该错误意味着cb未被识别为函数。您需要传递回调函数,正如我在上面的回答中所说的。请您再告诉我一点好吗?我对Javascript比较陌生,因为我主要使用PHP和类似的服务器端语言编写代码,对那些回调、承诺等有点困惑。哦,我明白了。回调和承诺的创建实际上是为了处理asncyrous。因此,nodejs是一种异步的特性,那么您就不能同时使用这两种方法。您可以选择使用回调或承诺。有很多简单的文档解释了回调和承诺的细节。