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 :- 使用本地护照时出现“缺少凭据”错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 nuxt auth 和 laravel 护照登录时出现错误 404