And*_*rdi 13 passwords mongodb node.js express passport.js
我已经设置了使用NodeJS/Passport更新用户密码.我按照这个伟大的指南:http://sahatyalkabov.com/how-to-implement-password-reset-in-nodejs/.
其中99%是有效的.我不得不修改它以包含一些条带功能.我担心我在某个地方遇到了严重的错误,我找不到它.用户目前能够一直完成向他们发送电子邮件,输入新密码并登录的过程.另一封电子邮件说明他们的密码已成功更新.一切都很完美 然而.由于某些原因.新密码未被保存.用户只能使用旧密码登录.我已经尝试了一切我能想到的解决这个问题的方法.
我有其他几个程序员看这个,但没有一个能够弄清楚它在世界上是如何起作用的.
目前的想法是会话可能没有正确结束,但我们试图破坏会话,但它仍然无法正常工作.
任何帮助非常感谢.
完整设置:
用户模型:
var UserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: String,
datapoint: String,
email: { type: String, required: true, unique: true },
resetPasswordToken: String,
resetPasswordExpires: Date
});
UserSchema.pre('save', function(next) {
var user = this;
var SALT_FACTOR = 5;
if (!user.isModified('password')) return next();
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
Run Code Online (Sandbox Code Playgroud)
注册新帐户 (这也有不相关的条带信息,但可能会导致问题.)
var newUser = new User({username: req.body.username, email: req.body.email, datapoint: req.body.datapoint});
User.register(newUser, req.body.password, function(err, user){
if(err){
console.log('Looks like there was an error:' + ' ' + err)
res.redirect('/login')
} else {
passport.authenticate("local")(req, res, function(){
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password
})
console.log('creating new account')
console.log('prepping charge')
var token = req.body.stripeToken; // Using Express
var charge = stripe.charges.create({
amount: 749,
currency: "usd",
description: "Example charge",
source: token,
}, function(err, charge) {
// asynchronously called
console.log('charged')
});
res.redirect('/jobquiz')
console.log(req.body.datapoint)
console.log(req.body.email)
});
}
});
});
Run Code Online (Sandbox Code Playgroud)
设置忘记密码发布
app.post('/forgot', function(req, res, next) {
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ email: req.body.email }, function(err, user) {
if (!user) {
// console.log('error', 'No account with that email address exists.');
req.flash('error', 'No account with that email address exists.');
return res.redirect('/forgot');
}
console.log('step 1')
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
console.log('step 2')
var smtpTrans = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'myemail',
pass: 'mypassword'
}
});
var mailOptions = {
to: user.email,
from: 'myemail',
subject: 'Node.js Password Reset',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/reset/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
console.log('step 3')
smtpTrans.sendMail(mailOptions, function(err) {
req.flash('success', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
console.log('sent')
res.redirect('/forgot');
});
}
], function(err) {
console.log('this err' + ' ' + err)
res.redirect('/');
});
});
app.get('/forgot', function(req, res) {
res.render('forgot', {
User: req.user
});
});
Run Code Online (Sandbox Code Playgroud)
设置更改密码帖子
app.get('/reset/:token', function(req, res) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
console.log(user);
if (!user) {
req.flash('error', 'Password reset token is invalid or has expired.');
return res.redirect('/forgot');
}
res.render('reset', {
User: req.user
});
});
});
app.post('/reset/:token', function(req, res) {
async.waterfall([
function(done) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user, next) {
if (!user) {
req.flash('error', 'Password reset token is invalid or has expired.');
return res.redirect('back');
}
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
console.log('password' + user.password + 'and the user is' + user)
user.save(function(err) {
if (err) {
console.log('here')
return res.redirect('back');
} else {
console.log('here2')
req.logIn(user, function(err) {
done(err, user);
});
}
});
});
},
function(user, done) {
// console.log('got this far 4')
var smtpTrans = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'myemail',
pass: 'mypass'
}
});
var mailOptions = {
to: user.email,
from: 'myemail',
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
' - This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n'
};
smtpTrans.sendMail(mailOptions, function(err) {
// req.flash('success', 'Success! Your password has been changed.');
done(err);
});
}
], function(err) {
res.redirect('/');
});
});
Run Code Online (Sandbox Code Playgroud)
我没有(或没有)发现你的代码有任何问题,但我有一个建议来追踪这个bug.
这段代码是有风险的.您可能会意外更新密码字段并触发rehash密码过程.
UserSchema.pre('save', function(next) {
var user = this;
var SALT_FACTOR = 12; // 12 or more for better security
if (!user.isModified('password')) return next();
console.log(user.password) // Check accident password update
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
Run Code Online (Sandbox Code Playgroud)
console.log在if (!user.isModified('password'))检查是否有意外的密码更新后放右.现在重试忘记密码,看看是否有任何错误.
*TD; LR将更新密码分隔为新方法而不是将其置于预先保存中,因为您可能会意外更新新密码以及其他字段
*更新:感谢#imns建议更好的SALT_FACTOR号码.
我认为问题可能在哈希函数中.尝试将您的代码复制到我的计算机上更简单但相似的实验中.
正如bcrypt文档在此处所述https://www.npmjs.com/package/bcrypt#to-hash-a-password
散列函数只接受3个参数,你发送4.而你的情况下的第三个参数是null.
这里有一些代码来说明问题和希望解决方案
在盐腌回调里面
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
Run Code Online (Sandbox Code Playgroud)
但是改为将第三个参数改为回调函数.
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20721 次 |
| 最近记录: |