无法注册Express中间件

时间:2015-05-25 02:09:44

标签: node.js 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);

1 个答案:

答案 0 :(得分:1)

使用

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

authorize方法会立即执行authorize(...)['ADMINISTRATOR', ...]数组作为req参数传递。因此,只要您运行代码并在用户对象不存在时死亡,就会调用它。即使它没有死在那,它也不会按预期工作。您正在混合中间件工厂功能。

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

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

通过拆分 factory 中间件功能,可以轻松创建参数化中间件功能(如您的情况):

// 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
)