如何在node.js中使用Mongoose/Mongodb进行passport身份验证

3

我正在构建我的第一个全栈Node.js应用程序,希望使用Passport进行身份验证。我看到了一个使用Passport将用户信息存储在用户数组中的教程。

passport-config.js文件:

const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')

function initialize(passport, getUserByEmail, getUserById) {
  const authenticateUser = async (email, password, done) => {
    const user = getUserByEmail(email)
    if (user == null) {
      return done(null, false, { message: 'No user with that email' })
    }

    try {
      if (await bcrypt.compare(password, user.password)) {
        return done(null, user)
      } else {
        return done(null, false, { message: 'Password incorrect' })
      }
    } catch (e) {
      return done(e)
    }
  }

  passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
  passport.serializeUser((user, done) => done(null, user.id))
  passport.deserializeUser((id, done) => {
    return done(null, getUserById(id))
  })
}

module.exports = initialize

server.js文件

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').config()
}

const express = require('express')
const app = express()
const bcrypt = require('bcrypt')
const passport = require('passport')
const flash = require('express-flash')
const session = require('express-session')
const methodOverride = require('method-override')

const initializePassport = require('./passport-config')
initializePassport(
  passport,
  email => users.find(user => user.email === email),
  id => users.find(user => user.id === id)
)

const users = []

app.set('view-engine', 'ejs')
app.use(express.urlencoded({ extended: false }))
app.use(flash())
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))

app.get('/', checkAuthenticated, (req, res) => {
  res.render('index.ejs', { name: req.user.name })
})

app.get('/login', checkNotAuthenticated, (req, res) => {
  res.render('login.ejs')
})

app.post('/login', checkNotAuthenticated, passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/login',
  failureFlash: true
}))

app.get('/register', checkNotAuthenticated, (req, res) => {
  res.render('register.ejs')
})

app.post('/register', checkNotAuthenticated, async (req, res) => {
  try {
    const hashedPassword = await bcrypt.hash(req.body.password, 10)
    users.push({
      id: Date.now().toString(),
      name: req.body.name,
      email: req.body.email,
      password: hashedPassword
    })
    res.redirect('/login')
  } catch {
    res.redirect('/register')
  }
})

app.delete('/logout', (req, res) => {
  req.logOut()
  res.redirect('/login')
})

function checkAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return next()
  }

  res.redirect('/login')
}

function checkNotAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return res.redirect('/')
  }
  next()
}

app.listen(3000)

我正在使用mongoDb数据库作为我的应用程序数据存储,希望将用户信息保存在我的数据库中。我已经在注册路由中进行了必要的更改,并且成功地将数据保存到了我的数据库中。

app.post('/register', checkNotAuthenticated, async (req, res) => {
    try {
      const hashedPassword = await bcrypt.hash(req.body.password, 10)
      
      const users = new User({
        name: req.body.name,
        email: req.body.email,
        password: hashedPassword
    })
      await users.save()
      res.redirect('/login')
               
     }
     
     catch(err){
         console.log(err)
         res.redirect('/register')     }
})

尝试使用存储的用户数据登录时,出现以下错误:
错误:需要数据和哈希参数 位于Object.compare (C:\AIT715\reactlogin\node_modules\bcrypt\bcrypt.js:208:17) 位于C:\AIT715\reactlogin\node_modules\bcrypt\promises.js:29:12 新Promise () 对象module.exports.promise (C:\AIT715\reactlogin\node_modules\bcrypt\promises.js:20:12) 位于Object.compare (C:\AIT715\reactlogin\node_modules\bcrypt\bcrypt.js:204:25) 位于Strategy.authenticateUser [as _verify] (C:\AIT715\reactlogin\passport-config.js:14:24) 位于processTicksAndRejections (internal/process/task_queues.js:95:5)
尝试对passport-config.js文件进行如下更改,但未成功。
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
const User = require('./models/user')

function initialize(passport, getUserByEmail, getUserById) {
  const authenticateUser = async (email, password, done) => {
    const user = await User.find({email:email});
    console.log(user);
    if (user == null) {
      return done(null, false, { message: 'No user with that email' })
    }

    try {
      if (await bcrypt.compare(password, user.password)) {
        return done(null, user)
      } else {
        return done(null, false, { message: 'Password incorrect' })
      }
    } catch (e) {
      return done(e)
    }
  }

当我使用console.log(user)时,我可以看到数据,但是当我尝试使用console.log(user.email)时,我得到了undefined。有人可以建议我在这里做错了什么?或者我需要对passport-config文件进行哪些更改才能使其起作用。非常感谢任何线索或帮助。


感谢您的评论@fabian。我已确保密码确实是原始的和散列的。我有一种感觉,在const user = await User.find({email:email});之后我的代码出了问题。原因是我尝试测试其他条件,比如输入一个不存在的用户,但我仍然得到相同的响应。 - Ali Zeeshan
2个回答

1
const passwordMatch = await bcrypt.compare(password, user.password);

请确保您提供的是原始密码和哈希密码。这将返回一个布尔值。


0
如果有人在未来看到这个,请注意:对我而言,使用findOne代替find有效。
const user = await User.findOne({email:email});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接