【问题标题】:Use multiple local strategies in PassportJS在 PassportJS 中使用多种本地策略
【发布时间】:2013-12-01 21:19:15
【问题描述】:

我正在尝试对 PassportJS 使用多种 LOCAL 策略。我没有尝试使用本地、facebook 和 gmail 等。 我有两组用户存储在不同的对象中,我想使用本地策略对两者进行身份验证。就目前而言,我不能对两者使用相同的本地策略,因为它们具有不同的对象属性,这让我查询不同的对象。有没有办法做到这一点?或者对此提出任何建议将不胜感激。

【问题讨论】:

  • 我不知道我认为坚持不使用 passportjs,使用 bcrypt 和随机盐进行散列并不是什么难的问题
  • 对于寻找 NestJs 解决方案的人们,refer to this answer

标签: node.js local passport.js


【解决方案1】:

您可以命名您的本地策略以将它们分开。

// use two LocalStrategies, registered under user and sponsor names

      // add other strategies for more authentication flexibility
  passport.use('user-local', new LocalStrategy({
      usernameField: 'email',
      passwordField: 'password' // this is the virtual field on the model
    },
    function(email, password, done) {
      User.findOne({
        email: email
      }, function(err, user) {
        if (err) return done(err);

        if (!user) {
          return done(null, false, {
            message: 'This email is not registered.'
          });
        }
        if (!user.authenticate(password)) {
          return done(null, false, {
            message: 'This password is not correct.'
          });
        }
        return done(null, user);
      });
    }
  ));

    // add other strategies for more authentication flexibility
    passport.use('sponsor-local', new LocalStrategy({
            usernameField: 'username',
            passwordField: 'password' // this is the virtual field on the model
        },
        function(username, password, done) {
            Sponsor.findOne({
                'primaryContact.username': username
            }, function(err, sponsor) {
                if (err) return done(err);

                if (!sponsor) {
                    return done(null, false, {
                        message: 'This email/username is not registered.'
                    });
                }
                if (!sponsor.authenticate(password)) {
                    return done(null, false, {
                        message: 'This password is not correct.'
                    });
                }
                return done(null, sponsor);
            });
        }
    ));

后来的控制器代码通过名称引用它们。

/**
 * User Login
 */
exports.loginUser = function (req, res, next) {
    passport.authenticate('user-local', function(err, user, info) {
        var error = err || info;
        if (error) return res.json(401, error);

        req.logIn(user, function(err) {

            if (err) return res.send(err);
            res.json(req.user.userInfo);
        });
    })(req, res, next);
};

/**
 * Sponsor Login
 */
exports.loginSponsor = function (req, res, next) {
    passport.authenticate('sponsor-local', function(err, sponsor, info) {
        var error = err || info;
        if (error) return res.json(401, error);

        req.logIn(sponsor, function(err) {
            if (err) return res.send(err);
            res.json(req.sponsor.profile);
        });
    })(req, res, next);
};

稍后当需要序列化您的用户时,您可能想要执行类似的操作。

// serialize
passport.serializeUser(function(user, done) {            
  if (isUser(user)) {
    // serialize user
  } else if (isSponsor(user)) {
    // serialize company
  }
});

【讨论】:

  • 感谢您的评论,我使用了类似的解决方案。不过还是谢谢你的回复!
  • 也使用了类似的,但目录不同。非常感谢。在准备好(并且当我自己真正理解它时)它会发布一个新的答案来解释我的解决方案。
  • 这在文档中的任何地方吗?
  • 我怎样才能通过使用 passport-local-mongoose 包来做同样的事情
  • 如何反序列化用户?我的一种策略是查询来宾表,而另一种策略是查询办公室表。
【解决方案2】:

我认为这是不可能的,因为据我所知,当第一个策略失败时,您需要某种方法将请求“移交”给第二个策略,而我认为这是不可能的。

但您也许可以使用一种本地策略,并尝试使用这两种方法验证传入的数据。

作为一个简单的例子(使用 Mongoose 作为示例数据库):

passport.use(new LocalStrategy(function(username, password, done) {
  Model1.findOne({ username : username }, function(err, user) {
    // first method succeeded?
    if (!err && user && passwordMatches(...)) {
      return done(null, user);
    }
    // no, try second method:
    Model2.findOne({ name : username }, function(err, user) {
      // second method succeeded?
      if (! err && user && passwordMatches(...)) {
        return done(null, user);
      }
      // fail! 
      done(new Error('invalid user or password'));
    });
  }); 
}));

对于序列化/反序列化,您可能需要在传递给 doneuser 对象中存储一些属性,以表示反序列化用户所需的模型。

【讨论】:

  • 我忘了接受这个,但谢谢!从这里我明白了我需要做什么。!
【解决方案3】:

您可以将这样的东西用于多种本地策略

passport.use('local.one', myLocalStrategy1);
passport.use('local.two', myLocalStrategy2);
passport.use('local.three', myLocalStrategy3);

...

app.get('/login/s1', passport.authenticate('local.one');
app.get('/login/s2', passport.authenticate('local.two');
app.get('/login/s3', passport.authenticate('local.three');

【讨论】:

    【解决方案4】:

    1)在用户注册表中保存默认角色:数据库中的'客户' 2)在管理员注册表中保存默认角色:数据库中的'admin'

    [Note- If you use mongodb as a database in registration schema make-
    
    role:{
    type: String,
    default: 'customer' or 'admin' //Manage respectively
    },
    
    Important- 'This uses cookie for session login'
    'You can do this on your own way :)']
    

    对于策略

    passport.use('user-local',
            new LocalStrategy({ usernameField: 'phone', passwordField: 'password' },
     (phone, password, done) => {
                // Match user
                User.findOne({
                    phone: phone
                }).then(user => {
                    if (!user) {
                        return done(null, false, { message: 'The phone not registered' });
                    }
    
                    // Match password
                    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('admin-local',
            new LocalStrategy({ usernameField: 'phone', passwordField: 'password' },
     (phone, password, done) => {
                // Match user
                Admin.findOne({
                    phone: phone
                }).then(user => {
                    if (!user) {
                        return done(null, false, { message: 'The phone not registered' });
                    }
    
                    // Match password
                    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.serializeUser((user, done) => {
            done(null, { _id: user.id, role: user.role });
    });
    

    用于反序列化

    passport.deserializeUser((login, done) => {
            if (login.role === 'customer') {
                User.findById(login, function (err, user) {
                    if (user)
                        done(null, user);
                    else
                        done(err, { message: 'User not found' })
                });
            }
            else if (login.role === 'admin') {
                Admin.findById(login, (err, admin) => {
                    if (admin)
                        done(null, admin);
                    else
                        done(err, { message: 'Admin not found' })
                });
            }
            else {
                done({ message: 'No entity found' }, null);
            }
        });
    

    【讨论】:

      【解决方案5】:
      1. 创建两个本地策略

        passport.use('userLocal', new LocalStrategy(User.authenticate())); passport.use('clientLocal', new LocalStrategy(Client.authenticate()));

      2.验证

      passport.authenticate('userLocal')(req, res, function () {
          res.redirect('/profile');
        });
      and
      passport.authenticate('clientLocal')(req, res, function () {
          res.redirect('/client');
        });
      

      3.对于serializeUser和deserializeUser

      passport.serializeUser(function(user, done) { 
        done(null, user);
      });
      
      passport.deserializeUser(function(user, done) {
        if(user!=null)
          done(null,user);
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-22
        相关资源
        最近更新 更多