如何将passport-jwt与ACL(访问控制列表)模式结合起来

时间:2018-03-27 01:38:47

标签: javascript node.js jwt passport.js acl

我使用的是passport-jwt。我正在尝试在我的系统中实现一个acl模式。我的系统中有一些不同的角色。我想控制他们对某些资源的访问权限。

我认为在基于令牌的身份验证中执行此操作的常用方法是为express.js编写中间件,该中间件将验证令牌并向“req.user”添加“角色”字段。然后将另一个中间件安装到每个路由,指定哪些角色可以访问它们。   所以我的问题是,如何将这种方法与passport-jwt结合起来。

加:   使用passport-jwt策略的常用方法是:

  app.get('/myapi', passport.authenticate('jwt', {session: false}),
    function(req, res, next){ ...})

我认为基于令牌的身份验证的常见方式是:

app.use(function(req, res, next){
  token = extractToken(req)
  jwt.verify(token, key, function(err, decoded) {
    if (err) {
      return res.send(err);
    } else {
      users.findOne({userId: decoded.userId}, function(err, user){
        if(!user) res.send('unknown')
        else{
          req.user = user //in which include a role field.
                      // for example: user.role = 'user' | 'manager'
        }
      })
    }
  });
})

and at every route:

function checkRole(roles){
  return function (req, res, next) {
    if (req.session.user && roles.includes(req.user.role)) {
        next();
    } else {
        res.send(403);
    }
  }
}

app.get('/myapi', checkRole(['user']), function(req, res){
  ....
})

1 个答案:

答案 0 :(得分:1)

我弄清楚自己。 我写了一个中间件来一起做这些事情:

/*middleware/acl.js */

export function checkRoleWithPassport(roles, passport, strategy, opts){
  return function(req, res, next){
    passport.authenticate(strategy, opts, function(err, user, info){                        
      if(err) res.status(403).send('forbidden')                                             
      else if(!user) res.status(403).send('forbidden')                                      
      else{                                                                                 
        if(roles.length == 0)                                                               
          next()                                                                            
        else if(roles.includes(user.role))                                                  
          next()                                                                            
        else                                                                                
          res.status(403).send('forbidden')                                                 
      }                                                                                     
    })(req, res, next)                                                                                    
  }                                                                                         
}     

/* route/index.js */
app.get('/myapi', checkRoleWithPassport(['manager'], passport, 
  'jwt', {session, false}), function(req, res){
   ...
})   // this should only allow the 'manager' to access /myapi