无法注册 Express 中间件

Unable to register Express middleware

我正在尝试为 Express 编写一个非常基本的中间件,用于检查用户是否具有访问资源所需的特定角色。在这之前我有另一个中间件,它为每个需要身份验证(和后续授权)的路由添加一个用户对象到请求req

因此,我这样定义授权中间件:

_ = require('lodash');

function authorize(req, res, next, roles){
    // check to see if user has one of the allowed roles
    if(_.contains(roles, req.user.role)){
        req.authorized = true;
        return next();
    }

    // otherwise, pass an error
    return next(new Error("Unauthorized"));
}

每个用户对象都有一个名为 role 的 属性,因此我使用 _.contains(roles, req.user.role) 来确定允许的角色是否包含用户分配的角色。

但是,当我这样做时,我会在启动 Express 服务器后立即得到 TypeError: Cannot read property 'role' of undefined。这对我来说似乎很奇怪,因为我什至没有提出请求,所以 req.user 当然在那之前是未定义的。

有办法解决这个问题吗?


我如何使用此中间件的示例:

var app = express();
var router = express.Router();
router.get('/protected/:id', authorize(['ADMINISTRATOR', 'MANAGER', 'OWNER']), controllers.protected.retrieve);

当您使用

注册路线时
router.get(
    '/protected/:id',
    authorize(['ADMINISTRATOR', 'MANAGER', 'OWNER']),
    controllers.protected.retrieve
)

authorize 方法直接由 authorize(...) 执行,['ADMINISTRATOR', ...] 数组作为 req 参数传递。因此,一旦您 运行 代码并在用户对象不存在时死亡,它就会被调用。即使它没有因此而死,它也不会按预期工作。您正在将 middlewarefactory 函数混合在一起。

Express middleware 是一个带有 (req, res, next) 签名的函数,您不会自己执行。您需要将 reference 传递给这样的中间件函数,Express 本身会在需要时根据请求执行它,即:

function authorize(req, res, next) {
    ...
};
router.get('/protected/:id', authorize, ...);

参数化的中间件函数,就像你的情况一样,可以通过拆分成一个 factory 和一个 middleware 函数来轻松创建:

// a factory function to create authorization middleware functions for given roles
function authorize(roles) {
    // create and return an actual authorization middleware function
    // to handle requests using the roles given when created
    return function(req, res, next) {
        if(_.contains(roles, req.user.role)){
            req.authorized = true;
            return next();
        }
        return next(new Error("Unauthorized"));
    }
}

router.get(
    '/protected/:id',
    authorize(['ADMINISTRATOR', 'MANAGER', 'OWNER']),
    controllers.protected.retrieve
)