首页 > 解决方案 > 多重身份验证不起作用 passport.js

问题描述

我正在尝试通过多种策略对多个用户进行身份验证。我有 2 个表,第一个是用户表,第二个是员工,但是当我尝试登录时它正在工作,它显示错误

     User not exist 

当我只使用单一身份验证策略时,它可以工作,但是当我使用多种策略时,它会显示错误

Auth.js

 const LocalStrategy = require('passport-local').Strategy
 const bcrypt = require('bcrypt')
 const User = require('../models/authUserModel')
 const Employee = require('../models/employeeModel')
 module.exports = function (passport) {
      passport.use("user-local",
         new LocalStrategy({usernameField: "email"}, function (email, password, done) {   
           User.findOne({email: email})
            .then(user => {
                if (!user) {
                    return done(null, false, ({message: 'Email not exist'}))
                }
                bcrypt.compare(password, user.password, (err, isMatch) => {
                    if (err) throw err
                    if (isMatch) {
                        return done(null, user)
                    } else {
                        return done(null, false, ({message: 'Password incorrect'}))
                    }
                })
            }).catch(err => console.log(err))

    })
)
passport.use('local',
    new LocalStrategy({usernameField:"email"}, function (email, password, done){
        Employee.findOne({email:"email"})
            .then(user=>{
                if(!user){
                    return done(null, false,'employee not exist')
                }
                bcrypt.compare(password, user.password, (err, isMatch)=>{
                    if(isMatch){
                        return done(null, user)
                    }
                    else {
                        return done(null, false, 'password or email is incorrect')
                    }
                })
            }).catch(err=>console.log(err))
    })
)

passport.serializeUser(function(user, done) {
    done(null, user.id);

});
passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
        done(err, user);
    });
});

}

登录.js

  let express = require('express');
  let router = express.Router();
  const passport = require('passport')



  router.get('/login', function(req, res, next) {
      res.render('login');
  })
  router.post('/login', function (req, res, next) {
     passport.authenticate("user-local", function (err, user, info) {
     if (err) {
        return next(err)
     }
     if (!user) {
     console.log('User not exist')
        return res.render('login')
    }
    req.logIn(user, function (err) {
        if (err) {
           return next(err)
        }  
        req.session.isLoggedIn = true
        req.session.user = user
        req.session.save(err => {
            console.log(err)
            if (req.isAuthenticated()) {
               return res.redirect('/customerMenu')
            }
            console.log('user not exist')
            return res.render('login')
         })
      })
  })(req, res, next)

passport.authenticate('local', function (err, user, info){

 if(err){
   return next(err)
}
if(!user)
{
  console.log("employee not exist")
  return res.render('login')
}

req.logIn(user,function (err){

  if(err){return next(err)}

  req.session.isLoggedIn = true

  req.session.user = user

  req.session.save(err=>{


    console.log(err)

    if (req.isAuthenticated()) {

      return res.redirect(200,'/employeeMenu')

    }

    console.log('user not exist')

    return res.render('login')

  })
})

  })(req, res, next)
 })
 function isLoggedIn(req, res, next){
     if(req.isAuthenticated()){
        req.isLogged = true
        return next();
     }
     else{
       req.isLogged = false
       return next()
     }
 }
 module.exports = isLoggedIn
 module.exports = router

标签: javascriptnode.jsauthenticationpassport.js

解决方案


我认为您需要编辑您的.serializeUser().deserializeUser()功能,以便护照知道您尝试序列化和反序列化的用户类型。

我过去的做法是使用 SessionConstructor 将用户的 id 和他们所在的用户类型放在一个对象中。然后,您可以在反序列化函数中使用它来确定您尝试登录的用户类型。

function SessionConstructor(userId, userGroup){
    this.userId = userId;
    this.userGroup = userGroup;
}

passport.serializeUser((user, done) => {
    let userGroup = 'user';
    if (//condition to tell if it is the other user type){
        userGroup = 'employee';
    };
    let sessionConstructor = new SessionConstructor(user.id, userGroup)

    done(null, sessionConstructor);
});

passport.deserializeUser((sessionConstructor, done) => {
    if (sessionConstructor.userGroup == 'user'){
        User.findById(sessionConstructor.userId).then(user => done(null, user));
    } else if (sessionConstructor.userGroup == 'employee'){
        Employee.findById(sessionConstructor.userId).then( employee=> done(null, employee));
    }
});

但是,您需要考虑其中的 if 语句的条件.serializeUser(),它将告诉您它是哪种类型的用户。如果您在发送到的用户对象中包含一个唯一标识符.serializeUser(),那么您可以检查它来判断。例如,在您的用户对象中有一个名为employee 的键,true如果是员工提交它,则该键的值是,false否则。如果你选择这个实现,它看起来像这样。

passport.serializeUser((user, done) => {
    let userGroup = 'user';
    if (user.employee){
        userGroup = 'employee';
    };
    let sessionConstructor = new SessionConstructor(user.id, userGroup)

    done(null, sessionConstructor);
});

除此之外,我认为下面的代码应该可以工作,但是请随时询问有关此方法的任何问题,我会尽力回答!

这是我了解如何执行此操作的链接。


推荐阅读