NodeJs :- 使用本地护照时出现“缺少凭据”错误

Posted

技术标签:

【中文标题】NodeJs :- 使用本地护照时出现“缺少凭据”错误【英文标题】:NodeJs :- Getting "missing credentials" error while using local passport 【发布时间】: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 感谢您的帮助。我更改了我的代码,它现在按要求工作 【参考方案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)
        )
)

【讨论】:

以上是关于NodeJs :- 使用本地护照时出现“缺少凭据”错误的主要内容,如果未能解决你的问题,请参考以下文章

Sails.js 0.11 和护照:“缺少凭据”错误

使用护照Laravel创建令牌时出现异常

使用 nuxt auth 和 laravel 护照登录时出现错误 404

向本地nodeJS服务器发出发布请求时出现AngularJS CORS错误

mongoose 中本地护照的身份验证错误

在护照 laravel 中刷新令牌时出现 TokenMismatchException