Javascript 使用bcryptjs比较哈希和密码返回false
我有通过电子邮件/updatePasswordViaEmail重置密码的终点 它工作得很好,它找到用户,我对密码进行哈希运算,我的问题是,当我在登录时进行比较时,它返回false。 我使用bcryptjs//Javascript 使用bcryptjs比较哈希和密码返回false,javascript,node.js,express,Javascript,Node.js,Express,我有通过电子邮件/updatePasswordViaEmail重置密码的终点 它工作得很好,它找到用户,我对密码进行哈希运算,我的问题是,当我在登录时进行比较时,它返回false。 我使用bcryptjs// const bcrypt = require("bcryptjs"); 我的盐轮是: const BCRYPT_SALT_ROUNDS = 8; 这是我的终点 router.put('/users/updatePasswordViaEmail', (req, res) =>
const bcrypt = require("bcryptjs");
我的盐轮是:
const BCRYPT_SALT_ROUNDS = 8;
这是我的终点
router.put('/users/updatePasswordViaEmail', (req, res) => {
User.findOne({
email: req.body.email,
resetPasswordToken: req.body.resetPasswordToken,
resetPasswordExpires: {
$gt: Date.now(),
},
}).then(user => {
console.log(user);
if (user == null) {
console.error('password reset link is invalid or has expired');
res.status(403).send('password reset link is invalid or has expired');
} else if (user != null) {
console.log('user exists in db');
bcrypt.hash(req.body.password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
console.log(hashedPassword);
user.password = hashedPassword;
user.resetPasswordToken = null;
user.resetPasswordExpires = null;
user.save(function (err) {
if (err) {
console.error('ERROR!');
}
});
}).then(() => {
console.log('password updated');
res.status(200).send({message: 'password updated'});
});
} else {
console.error('no user exists in db to update');
res.status(401).json('no user exists in db to update');
}
});
});
这是我的预存
userSchema.pre('save', async function (next) {
// Hash the password before saving the user model
const user = this;
if (user.isModified("password") || user.isNew) {
//Perform password hashing here
user.password = await bcrypt.hash(user.password, BCRYPT_SALT_ROUNDS)
} else {
return next();
}
});
在这里,当我尝试查看密码是否匹配时,它总是返回false:
userSchema.statics.findByCredentials = async (email, password) => {
// Search for a user by email and password.
const user = await User.findOne({email});
if (!user) {
throw new MyError({error: 'Invalid login credentials'})
}
const isPasswordMatch = await bcrypt.compare(password, user.password);
console.log(isPasswordMatch)// only comes false
if (!isPasswordMatch) {
throw new MyError({error: 'Invalid login credentials'})
}
return user
};
我的整个用户模型:
const mongoose = require('mongoose');
const bcrypt = require("bcryptjs");
const jwt = require('jsonwebtoken');
const uniqueValidator = require('mongoose-unique-validator');
const BCRYPT_SALT_ROUNDS = 8;
// Get the Schema constructor
const Schema = mongoose.Schema;
function MyError(message) {
this.message = message
}
MyError.prototype = new Error();
const userSchema = new Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
},
tokens: [{
token: {
type: String,
required: true
}
}],
resetPasswordToken: {
type: String,
},
resetPasswordExpires: Date,
userRooms: [{type: Schema.Types.ObjectId, ref: 'Room'}]
});
userSchema.pre('save', async function (next) {
// Hash the password before saving the user model
const user = this;
if (user.isModified("password") || user.isNew) {
//Perform password hashing here
user.password = await bcrypt.hash(user.password, BCRYPT_SALT_ROUNDS)
} else {
return next();
}
});
userSchema.methods.generateAuthToken = async function () {
// Generate an auth token for the user
const user = this;
const token = jwt.sign({_id: this._id, isAdmin: this.isAdmin}, "Stack", {
expiresIn: '1d' // expires in 365 days
}, process.env.JWT_KEY); //get the private key from the config file -> environment variable
console.log(token);
user.tokens = user.tokens.concat({token});
await user.save();
return token
};
userSchema.statics.findByCredentials = async (email, password) => {
// Search for a user by email and password.
const user = await User.findOne({email});
if (!user) {
throw new MyError({error: 'Invalid login credentials'})
}
const isPasswordMatch = await bcrypt.compare(password, user.password);
console.log(isPasswordMatch)// only comes false
if (!isPasswordMatch) {
throw new MyError({error: 'Invalid login credentials'})
}
return user
};
const User = mongoose.model('User', userSchema.plugin(uniqueValidator, {message: ''}));
module.exports = User;
解决方案:
我发现当我更新用户时,用户工作不正常,出现了一些问题,我将其更改为:
router.put('/users/updatePasswordViaEmail', async (req, res) => {
const salt = await bcrypt.genSalt(10);
const user = await User.findOne(
{email: req.body.email},
{resetPasswordToken: req.body.resetPasswordToken},
{
resetPasswordExpires: {
$gt: Date.now(),
}
}
);
if (user == null) {
console.error('password reset link is invalid or has expired');
res.status(403).send('password reset link is invalid or has expired');
} else if (user != null) {
console.log('user exists in db');
console.log(req.body.password);
let hashedPassword = await bcrypt.hash(req.body.password, salt);
const body = {
password: hashedPassword,
resetPasswordToken: null,
resetPasswordExpires: null
};
let updatedUser = await User.findOneAndUpdate(req.body.email, body);
console.log(updatedUser);
console.log('password updated');
res.status(200).send({message: 'password updated'});
} else {
console.error('no user exists in db to update');
res.status(401).json('no user exists in db to update');
}
});
router.post('/users/login', async (req, res) => {
//Login a registered user
try {
const email = req.body.email;
const password = req.body.password;
const userData = await User.findOne({email});
if (!userData) {
throw new MyError({error: 'Invalid login credentials'})
}
// if ((user.isVerified)) {//todo verify user
const isPasswordMatch = await bcrypt.compareSync(password, userData.password);
console.log(isPasswordMatch);
if (isPasswordMatch) {
const token = await userData.generateAuthToken();
let user = userData.toJSON();
delete user.password;
return res.send({user, token});
} else return res.status(400).send({password: 'Wrong password'});
// } else {
// return res.status(401).send({ msg: 'Account not verified' });
// }
} catch (e) {
console.log(e);
}
});
正如你所看到的,我使用findOneAndUpdate,它很有效
我将我的登录终点更改为:
router.put('/users/updatePasswordViaEmail', async (req, res) => {
const salt = await bcrypt.genSalt(10);
const user = await User.findOne(
{email: req.body.email},
{resetPasswordToken: req.body.resetPasswordToken},
{
resetPasswordExpires: {
$gt: Date.now(),
}
}
);
if (user == null) {
console.error('password reset link is invalid or has expired');
res.status(403).send('password reset link is invalid or has expired');
} else if (user != null) {
console.log('user exists in db');
console.log(req.body.password);
let hashedPassword = await bcrypt.hash(req.body.password, salt);
const body = {
password: hashedPassword,
resetPasswordToken: null,
resetPasswordExpires: null
};
let updatedUser = await User.findOneAndUpdate(req.body.email, body);
console.log(updatedUser);
console.log('password updated');
res.status(200).send({message: 'password updated'});
} else {
console.error('no user exists in db to update');
res.status(401).json('no user exists in db to update');
}
});
router.post('/users/login', async (req, res) => {
//Login a registered user
try {
const email = req.body.email;
const password = req.body.password;
const userData = await User.findOne({email});
if (!userData) {
throw new MyError({error: 'Invalid login credentials'})
}
// if ((user.isVerified)) {//todo verify user
const isPasswordMatch = await bcrypt.compareSync(password, userData.password);
console.log(isPasswordMatch);
if (isPasswordMatch) {
const token = await userData.generateAuthToken();
let user = userData.toJSON();
delete user.password;
return res.send({user, token});
} else return res.status(400).send({password: 'Wrong password'});
// } else {
// return res.status(401).send({ msg: 'Account not verified' });
// }
} catch (e) {
console.log(e);
}
});
如果你
console.log(user.password)
在那一点上,它是什么?@Ry-我得到一个像这样的散列密码:$2b$08$imb4no4vxcf8mjqijiuy9otnv7k3fo7txstvhi117ojtbgip/qooa,如果你console.log(password)
在同一点上,它是什么?@Ry-它没有定义,所以它会给我一个错误。设置user.password=hashedPassword
然后在pre('save')
hook中再次对其进行散列的方式。让事情变得混乱的简单方法。我建议使用两个不同的属性,user.password
和user.hashedPassword
,如果您的ORM允许,只将hashedPassword
保存到数据库中。(我不喜欢ORMs,所以也许有一种更典型的方式。)