【问题标题】:Express: call a middleware from another middlewareExpress:从另一个中间件调用一个中间件
【发布时间】:2016-03-31 19:40:22
【问题描述】:

我是 Express 4 的新手,我想知道如何实现这个东西:我正在使用 jwt 来验证我的 API 的使用者,为此我有一个漂亮的检查 jwt 令牌有效性的简单中间件:

var requireValidToken = function(req, res, next) {
  var token = req.body.token || req.query.token || req.headers['x-access-token'];
  if (token) {
    try {
      var decoded = jwt.verify(token, req.app.get('superSecret'));
    } catch(err) {
      return res.json({ success: false, message: 'Failed to authenticate token.' });  
    }
    req.user = decoded.user;
    next();
  } else {
    return res.status(403).send({ 
        success: false, 
        message: 'No token provided.' 
    });
  }
};

这工作得很好,但现在,我想扩展它以便能够检查用户的角色:

 router.get('/anAdminRoute', requireRole('ROLE_ADMIN'), function (req, res, next) {
      // some code...
 });

所以我为此添加了一个中间件:

var requireRole = function(role) {
  return function(req, res, next){
    // Dummy tests...
    if(req.user.role == roles.admin || req.user.role == role){
      next();
    } else {
      return res.status(403)({
        success: false,
        message: "Token valid, but you don't have the right permission to access this resource :)"
      });
    }
  }
}

但是由于这个 requireRole() 函数显然会检查一个有效的 jwt 令牌,我想知道如何在这个函数中调用我的 requireValidToken 中间件,因此不必为我想要保护的每条路由显式调用它。

一个简单的解决方案是不使用 requireValidToken 作为中间件,但我仍然希望能够使用它来保护某些路由

编辑:解决方案

链式中间件就是这么简单:

var middleware2 = function(param) {
  return function(req, res, next){
    middleware1(req, res, function(){
      // middleware2 code
    });
  }
}

如果有人感兴趣,我验证用户角色的最终工作解决方案:

var jwt = require('jsonwebtoken'),
  roles = require('../models/user').roles; 

// authentication middleware
// check if the given jwt token is valid
var requireValidToken = function(req, res, next) {
  var token = req.body.token || req.query.token || req.headers['x-access-token'];
  if (token) {
    try {
      var decoded = jwt.verify(token, req.app.get('superSecret'));
    } catch(err) {
      return res.json({ success: false, message: 'Failed to authenticate token.' });  
    }
    req.user = decoded.user;
    next();
  } else {
    return res.status(403).send({ 
        success: false, 
        message: 'No token provided.' 
    });
  }
};

var requireRole = function(role) {
  return function(req, res, next){
    requireValidToken(req, res, function(){
      if(req.user.role == roles.admin || req.user.role == role){
        next();
      } else {
        return res.status(403).send({
          success: false,
          message: "Token valid, but you don't have the right permission to access this resource :)"
        });
      }
    });
  }
}

module.exports = {
  requireValidToken: requireValidToken,
  requireRole: requireRole
}

【问题讨论】:

  • 晚了一点,但想指出,总的来说,即使令牌被加密——依赖客户端数据来确定特权级别,也是一个巨大的安全禁忌。理想情况下,令牌应该只验证用户的身份,并且应该从您控制的服务器端数据中提取权限和角色。如果您由于某种不明原因确实无法在服务器端存储用户权限/角色数据,我只会考虑此选项。

标签: node.js express


【解决方案1】:

完全误读了您的问题。如果您想在某些情况下调用requireValidToken,您可以将 req 和 res 对象以及匿名回调传递给中间件函数。如何获得中间件功能很大程度上取决于您的应用程序架构,因此我假设我的上下文中有 requireValidToken

var requireRole = function(role) {
  return function(req, res, next){
    // Dummy tests...

    requireValidToken(req, res, function () {
      if(req.user.role == roles.admin || req.user.role == role){
        next();
      } else {
        return res.status(403)({
          success: false,
          message: "Token valid, but you don't have the right permission to access this resource :)"
        });
      }
    });
  }
};

【讨论】:

  • 这个 javascript 回调语法会杀了我 :) 谢谢!很好的答案。
  • 帮了我很多忙!!
【解决方案2】:

这种语法对我有用。其中 auth 是另一个中间件模块

import auth from "../middlewares/auth.js";

export default function (req, res, next) {
  auth(req, res, function () {
    if (req.params.id !== req.user._id)
      return res
        .status(401)
        .send({ status: "error", message: "User does not have rights to modify this data." });

    next();
  });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多