【问题标题】:Passport.js multiple local strategies and req.userPassport.js 多个本地策略和 req.user
【发布时间】:2016-03-20 08:56:24
【问题描述】:

我的网络应用程序的客户端希望完全将普通用户和管理员分开,因此我正在尝试为 passport.js 实施两种本地策略:

passport.use('local', new LocalStrategy({
    usernameField: 'email'
}, function(email, password, done) {
    User.findOne({ email: email }, function(err, user) {
        if (err) return done(err);
        if (!user) return done(null, false, { message: 'Wrong email or password.' });
        if (!user.validPassword(password)) return done(null, false, { message: 'Wrong email or password.' });
        done(null, user);
    });
}));

passport.use('admin', new LocalStrategy({
    usernameField: 'email'
}, function(email, password, done) {
    Admin.findOne({ email: email }, function(err, admin) {
        if (err) return done(err);
        if (!admin) return done(null, false, { message: 'Wrong email or password.' });
        if (!admin.validPassword(password)) return done(null, false, { message: 'Wrong email or password.' });
        done(null, admin);
    });
}));

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

passport.deserializeUser(function(id, done) {

    Admin.findById(id, function(err, admin) {
        if (err) return done(err);
        if (admin) return done(null, admin);
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });
});

然后在我的 API 管理路由器中:

router.post('/', function(req, res, next) {
    if (typeof req.body.email === 'undefined') return res.json({ success: false, message: 'Email not supplied.' });
    if (!validator.isEmail(req.body.email)) return res.json({ success: false, message: 'Wrong email format.' });
    if (typeof req.body.password === 'undefined') return res.json({ success: false, message: 'Password not supplied.' });
    if (req.body.password.length === 0) return res.json({ success: false, message: 'Password not supplied.' });

    passport.authenticate('admin', function(err, admin, info) {
        if (!admin) return res.json({ success: false, message: info.message });
        req.logIn(admin, function(err) {
            if (err) return res.json({ success: false, message: 'Server error.', reason: err });
            console.log('user:');
            console.log(req.user); // both users and admins go here
            console.log('admin:');
            console.log(req.admin); // undefined
            res.json({ success: true });
        });
    })(req, res, next);

});

事实上,我在这里关注答案:https://stackoverflow.com/a/21898892/1830420,而 Matthew Payne 得到两个会话变量:req.userreq.sponsor。就我而言,即使管理员进行了身份验证,它也会被写入req.user。现在,试图实现我的客户完全分离用户和管理员的愿望,我想得到req.userreq.admin,但每次它被写入req.user。我认为更改 LocalStrategy 名称会有所帮助,但 passport.js 似乎忽略了策略名称 模型名称。

非常感谢任何帮助。

附:我知道我可以让每个人都在User 模型中,并编写一些中间件来保护基于角色的某些路由,但话又说回来,不幸的是,我不能在这里选择。

【问题讨论】:

    标签: node.js express passport.js passport-local


    【解决方案1】:

    很遗憾,Passport 无法做到这一点。您将需要创建快速中间件来处理管理员身份验证。

    【讨论】:

    • 叹息.. 好吧,应用程序方面,让管理员和用户作为具有角色的用户方案并不是什么大不了的事:D 必须回滚到角色检查中间件。谢谢!
    【解决方案2】:

    和 Hya 一样回答护照不利于授权......

    您需要使用中间件来设置管理员上下文和管理员角色:

    // add this middlewares after your routes...
    
    // set admin context and others things like admin templates
    app.use('/admin/*', function adminContext(req, res, next) {
      // set admin context
      req.isAdmin = true;
    
      next();
    });
    
    
    // then get roles for authenticated user in your passport stategy:
    app.use(function getUserRoles(req, res, next) {
      req.userRoleNames = [];
    
      if (req.isAuthenticated()) {
        req.userRoleNames.push('authenticated');
      } else {
        req.userRoleNames.push('unAuthenticated');
        return next(); // skip role load if dont are authenticated
      }
    
      // get user roles, you may get roles from DB ...
      // and if are admin add its role
      req.userRoleNames.push('administrator');
    
      next();
    
    });
    
    // and check roles in admin page
    app.get('/admin/admin-page/', function (req, res, next) {
      if (req.userRoleNames.indexOf('administrator') == -1) return res.status(403).send('forbidden');
    
      console.log('roles:', req.userRoleNames);
    
      res.status(200).send('Hey you are the administrator!');
    });
    

    查看 we.js 核心以查看一种高级角色和权限实现:https://github.com/wejs/we-core

    【讨论】:

    • 谢谢,我已经对@hya 的回答叹了口气并回滚到状态,在那里我有角色和中间件来检查用户是否具有路由的特定角色。
    猜你喜欢
    • 2020-12-26
    • 2018-11-10
    • 2015-01-01
    • 2017-09-18
    • 2014-03-20
    • 2014-11-12
    • 2014-01-11
    • 1970-01-01
    • 2013-08-29
    相关资源
    最近更新 更多