Erstens weiß ich, dass die gleiche Frage schon oft vor mir gestellt wurde, aber ich konnte keine Antwort in einer dieser Fragen finden, die ich auf StackOverflow gefunden.bcrypt Passwort im Vergleich zu vergleichen Methode führt immer mit Fehler
Ich begann erst vor kurzem express
und zum ersten Mal lernen, ich versuche Anwendung, sowohl, Backend und Frontend mit JavaScript-Bibliotheken (die sich aus PHP
Welt) zu erstellen. Ich habe ein MongoDB
Modell-Schema mit einigen Vorarbeiten und eine Funktion, die das eingegebene Passwort zu einem Hash-Passwort in der Datenbank gespeichert erklärt. Alles andere scheint gut zu funktionieren, außer dass die Methode comparePassword
niemals ein passendes Passwort zurückgibt.
Ich benutze eine bcryptjs
Bibliothek für Passwort Hashing und Vergleich und eine passport
Bibliothek für die Authentifizierung.
User-Modell(Modelle/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);
Strategie Authentication(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
});
}
));
Und schließlich, Meine Route zum Anmelden(routes/a uth.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;
EDIT:
Wenn ich entfernen Sie die console.log
Ausgabe in:
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);
});
};
und versuchen, die Callback-Funktion auszuführen, werde ich die folgende Fehlermeldung erhalten :
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)
EDIT 2:
So konnte ich endlich die Passwörter vergleichen und konnte console.log
ob die Passwörter übereinstimmen oder nicht. Mit Promises konnte ich das durchziehen. Jetzt bin ich mir nicht sicher, wie ich dieses Versprechen an den Handler passport
weiterleiten kann, damit es die Benutzerergebnisse für die Routen zurückgeben kann.
Hier ist die comparePassword
Methode:
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);
});
});
};
und die 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);
})
});
}
));
ich dies versucht und das Verhalten ist immer noch das gleiche wie mit meinem ursprünglichen Code: Wenn ich versuche, die Übereinstimmung zu trösten, wird es ausgegeben "Passwörter stimmen nicht überein" und wenn ich die Rückkehr und entfernen versuche den Callback bekomme ich einen Fehler: 'cb (null, isMatch); TypeError: undefined ist keine Funktion –
Oh. Ich merke gerade, dass Sie nach console.log eine Zeile in die Zeile setzen. Was ist der Punkt? Möchten Sie den Fehler verhindern? Sie können es nicht direkt vergleichen, indem Sie äquivalentString verwenden, es wird nicht funktionieren. Lassen Sie bcrypt.compare damit umgehen und versuchen Sie console.log (isMatch), was Sie bekommen werden. – digit
Dieser Fehler bedeutet, dass cb nicht als eine Funktion erkannt wird. Sie müssen Callback-Funktion übergeben, wie ich in der obigen Antwort angegeben habe. – digit