gpt4 book ai didi

javascript - bcrypt 密码与比较方法进行比较总是会出现错误

转载 作者:行者123 更新时间:2023-11-28 05:07:00 25 4
gpt4 key购买 nike

首先,我知道同样的问题在我之前已经被问过很多次,但我在 StackOverflow 上找到的任何问题都找不到答案。

我最近刚刚开始学习express,并且第一次尝试使用以下命令创建应用程序(后端和前端)javascript 库(来自 PHP 世界)。我已经声明了一个 MongoDB 模型架构,其中包含一些前期工作和一个将输入的密码与存储在数据库中的散列密码。除了 comparePassword 方法永远不会返回匹配的密码之外,其他一切似乎都工作得很好。

我使用 bcryptjs 库进行密码散列和比较,并使用 passport 库进行身份验证。

用户模型 (models/user.js):

var mongoose            = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcryptjs');
SALT_WORK_FACTOR = 10;

var userSchema = new Schema({
//id: ObjectId,
email: {
type: String,
unique: true,
required: true
},
name: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});

userSchema.pre('save', function(next) { // Hash the password before adding it to the database
var user = this;

// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();

// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);

// hash the password using our new salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);

// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});

userSchema.methods.comparePassword = function(candidatePassword, cb) {
var user = this;
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);
});
};
module.exports = mongoose.model('User', userSchema);

身份验证策略(config/passport.js):

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

passport.use(new LocalStrategy({
usernameField: 'email'
},
function(username, password, done) {
User.findOne({ email: username }, function (err, user) {
if (err) { return done(err); }

if (!user) { // Return if user not found in database
return done(null, false, {
message: 'User not found'
});
}

// It will always output "Incorrect creditentials"
if (!user.comparePassword(password)) {
return done(null, false, {
error: true,
message: 'Incorrect creditentials'
});
}
return done(null, user); // If credentials are correct, return the user object
});
}
));

最后,我的登录路线 (routes/auth.js):

var router = require('express').Router(); // get router instance
var request = require('request');
var passport = require('passport');
var User = require('../../models/user');
var tokenAuth = require('../../middlewares/token');

router.post('/signin', function(req, res) {
passport.authenticate('local', function(err, user, info){
var token;

if (err) { // If Passport throws/catches an error
res.status(404).json(err);
return;
}

if(user) { // If a user is found
token = user.generateJwt();
res.status(200);
res.json({
"token" : token
});
} else {
// If user is not found
res.status(401).json(info);
}
})(req, res);

});

module.exports = router;

编辑:

如果我删除以下位置的 console.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 密码是否匹配。我能够通过 Promise 实现这一目标。现在我不确定如何将该 Promise 传递给 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 比较中传递回调。确保将纯文本密码作为参数传递,并将其与数据库中的哈希密码进行比较。

而不是这样做

 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
}
});

并在bcrypt比较方法中,更改回调参数,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);
})
});
}
));

路由中间件

我猜你的路线是这样的

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');
});

关于javascript - bcrypt 密码与比较方法进行比较总是会出现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41658687/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com