【问题标题】:NodeJs :- Getting "missing credentials" error while using local passportNodeJs :- 使用本地护照时出现“缺少凭据”错误
【发布时间】:2020-05-12 22:22:27
【问题描述】:

我试图实现一个用户可以重置密码的功能。我已经尝试了下面的代码,虽然我没有收到任何错误,但它没有更新密码。密码相同,即旧密码。

我的用户模型文件如下:-

const mongoose = require('mongoose');
var passportLocalMongoose = require("passport-local-mongoose");

const LoginUserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    unique: true,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  date: {
    type: Date,
    default: Date.now
  },
    resetPasswordToken: String,
    resetPasswordExpires: Date
});

// The below is used so as to allow passport to reset password
LoginUserSchema.plugin(passportLocalMongoose);

const LoginUser = mongoose.model('LoginUser', LoginUserSchema);

module.exports = LoginUser; 

我的路由文件如下:-

const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
var async = require("async");
// Load User model
const User = require('../models/loginuser');
var nodemailer = require("nodemailer");
var crypto = require("crypto");
// Load Auth from files
const { ensureAuthenticated, forwardAuthenticated } = require('../config/auth');

// Login Page
router.get('/login', forwardAuthenticated, (req, res) => res.render('login'));

// Register Page
router.get('/register', (req, res) =>{
  if(typeof req.user == "undefined"){
    console.log("HERE IT IS");
    res.redirect('/users/login');
  }
  if (req.user.email == "theamarex@gmail.com"){
  res.render('register')
  }else{
    res.redirect('/users/login');
  }
})

// Register
router.post('/register', (req, res) => {

  const { name, email, password, password2 } = req.body;
  let errors = [];

  if (!name || !email || !password || !password2) {
    errors.push({ msg: 'Please enter all fields' });
  }

  if (password != password2) {
    errors.push({ msg: 'Passwords do not match' });
  }

  if (password.length < 6) {
    errors.push({ msg: 'Password must be at least 6 characters' });
  }

  if (errors.length > 0) {
    res.render('register', {
      errors,
      name,
      email,
      password,
      password2
    });
  } else {
    User.findOne({ email: email }).then(user => {
      if (user) {
        errors.push({ msg: 'Email already exists' });
        res.render('register', {
          errors,
          name,
          email,
          password,
          password2
        });
      } else {
        const newUser = new User({
          name,
          email,
          password
        });

        bcrypt.genSalt(10, (err, salt) => {
          bcrypt.hash(newUser.password, salt, (err, hash) => {
            if (err) throw err;
            newUser.password = hash;
            newUser
              .save()
              .then(user => {
                req.flash(
                  'success_msg',
                  'You are now registered and can log in'
                );
                res.redirect('/users/login');
              })
              .catch(err => console.log(err));
          });
        });
      }
    });
  }
});

// Login
router.post('/login', (req, res, next) => {
  passport.authenticate('local', {
    successRedirect: '/users/dashboard',
    failureRedirect: '/users/login',
    failureFlash: true
  })(req, res, next);
});

// Logout
router.get('/logout', (req, res) => {
  req.logout();
  req.flash('success_msg', 'You are logged out');
  res.redirect('/users/login');
});

// Dashboard
router.get('/dashboard', ensureAuthenticated, (req, res) =>{
  res.render('dashboard', {
    user: req.user
  })
}
);

// Forgot password url
router.get('/forgot', function(req, res) {
  res.render('forgot');
});

router.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) {
          req.flash('error', 'No account with that email address exists.');
          return res.redirect('/users/forgot');
        }

        user.resetPasswordToken = token;
        user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

        user.save(function(err) {
          done(err, token, user);
        });
      });
    },
    function(token, user, done) {
      var smtpTransport = nodemailer.createTransport({
        service: 'Gmail', 
        auth: {
          user: '',
          pass: ''
        }
      });
      var mailOptions = {
        //to: user.email,
        to: "cechque@gmail.com",
        from: 'theamarexrouting@gmail.com',
        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 + '/users/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        console.log('mail sent');
        req.flash('success', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
        done(err, 'done');
      });
    }
  ], function(err) {
    if (err) return next(err);
    res.redirect('/users/forgot');
  });
});

// Reset password url
router.get('/reset/:token', function(req, res) {
  User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
    if (!user) {
      req.flash('error', 'Password reset token is invalid or has expired.');
      return res.redirect('/forgot');
    }
    res.render('reset', {token: req.params.token});
  });
});



 router.post('/reset/:token', function(req, res) {
  async.waterfall([
    function(done) {
      User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
        if (!user) {
          req.flash('error', 'Password reset token is invalid or has expired.');
          return res.redirect('back');
        }
        if(req.body.password === req.body.confirm) {
            user.resetPasswordToken = undefined;
            user.resetPasswordExpires = undefined;
            user.password = req.body.password;

          bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(user.password, salt, (err, hash) => {
              if (err) throw err;
              user.password = hash;
                user.save(function(err) {
                  req.login(user, function(err) {
                    console.log(user);
                    done(err, user);
                  });
                });
            });
          });
        } else {
            req.flash("error", "Passwords do not match.");
            return res.redirect('back');
        }
      });
    },
        function(user, done) {
          var smtpTransport = nodemailer.createTransport({
            service: 'Gmail', 
            auth: {
              user: '',
              pass: ''
            }
          });
          var mailOptions = {
            to: "",
            from: '',
            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'
          };
          smtpTransport.sendMail(mailOptions, function(err) {
            req.flash('success', 'Success! Your password has been changed.');
            done(err);
          });
        }
      ], function(err) {
        res.redirect('/users/dashboard');
      });
    });


    module.exports = router;

我有点困惑我哪里出错了。我试图在网上和这个论坛上搜索各种答案,但它并没有帮助我。请帮帮我。谢谢

【问题讨论】:

  • 看起来密码的存储位置不匹配 - 在创建用户帐户时,password 字段是手动填充的,但对于密码更改,passport-local-mongoose 用于密码更改(通过 @987654325 @) - 后者默认使用hash 字段来存储密码哈希,并且看起来这没有被覆盖(没有提供hashField 配置选项)。
  • 我建议在这两种情况下都有一个通用的程序来生成密码 - 通过在创建帐户时放弃 bcrypt 周围的整个逻辑,让passport-local-mongoose 完成它的工作。否则,您可以删除passport-local-mongoose,然后手动生成新密码哈希并将其分配给用户(而不是调用setPassword) - 与POST /register 中的方法相同。
  • 更改密码后尝试登录时是否会出现“缺少凭据”错误?如果是这样,是否可以在更改密码之前使用新帐户登录?
  • 最新更新后看起来更清晰。在最新状态下,passport-local-mongoose 既不用于创建帐户也不用于重置密码,但仍用于登录。继续这样,您应该从POST /login 中删除passport.authenticate 并用手动程序替换它:从用户文档中获取密码passport.authenticate 和salt,计算哈希并与用户文档中的哈希进行比较。相等时创建会话,否则重定向 fo /login。或者,在所有 3 种情况下仍然依赖 passport-local-mongoose
  • @SergeyLapin 感谢您的帮助。我更改了我的代码,它现在按要求工作

标签: javascript node.js mongoose passport.js bcrypt


【解决方案1】:

我已对代码进行了更改。你在这里用错了passport-local-mongoose

   //register    
    if (errors.length > 0) {
              res.render('register', {
                errors,
                name,
                username,
                password,
                password2
              });
            } else {
              User.findOne({ username: username }).then(user => {
                if (user) {
                  errors.push({ msg: 'username already exists' });
                  res.render('register', {
                    errors,
                    name,
                    username,
                    password,
                    password2
                  });
                } else {
                  const newUser = new User({
                  name,
                  username,
                  password
                  });

                  User.register(newUser, req.body.password, function(err, user){
                      console.log(req.body)
                      if(err){
                          console.log(err);
                          return res.render("register", {error: err.message});
                      }
                      passport.authenticate("local")(req, res, function(){
                      req.flash("success", "Successfully Signed Up! Nice to meet you " + req.body.name);
                      res.redirect('/users/login');
                      });
                  });
                }
              });
            }

    // forgot password

    router.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({ username: req.body.username }, function(err, user) {
            if (!user) {
              req.flash('error', 'No account with that username address exists.');
              return res.redirect('/users/forgot');
            }

            user.resetPasswordToken = token;
            user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

            user.save(function(err) {
              done(err, token, user);
            });
          });
        },

//reset token
async.waterfall([
    function(done) {
      User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
        if (!user) {
          req.flash('error', 'Password reset token is invalid or has expired.');
          return res.redirect('back');
        }
        if(req.body.password === req.body.confirm) {
          user.setPassword(req.body.password, function(err) {
            user.resetPasswordToken = undefined;
            user.resetPasswordExpires = undefined;

            user.save(function(err) {
              req.logIn(user, function(err) {
                done(err, user);
              });
            });
          })
        } else {
            req.flash("error", "Passwords do not match.");
            return res.redirect('back');
        }
      });
    },

【讨论】:

    【解决方案2】:

    我使用护照获得了更改密码路线。也许它对你有用。这里是:

    router.post('/changepassword', passport.authenticate('jwt', { session: false }), (req, res) => {
        User.findOne({ username: req.user.username })
            .then(user => {
                if (!user) {
                    return res.status(404).json({
                        success: false
                    });
                } else if (req.body.password !== req.body.confirm_password) {
                    return res.status(404).json({
                        msg: "Wachtwoorden komen niet overeen",
                        success: false
                    });
                }
                bcrypt.genSalt(10, (err, salt) => {
                    bcrypt.hash(req.body.password, salt, (err, hash) => {
                        user.password = hash;
                        user.save().then(user => {
                            return res.status(201).json({
                                success: true,
                                msg: "Wachtwoord veranderd"
                            });
                        })
                    });
                });
            })
            .catch(err => {
                console.log(err)
            })
    })
    

    【讨论】:

      猜你喜欢
      • 2018-06-02
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 2016-08-12
      • 2019-09-12
      • 2020-10-18
      • 2020-09-29
      相关资源
      最近更新 更多