无法注册 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
参数传递。因此,一旦您 运行 代码并在用户对象不存在时死亡,它就会被调用。即使它没有因此而死,它也不会按预期工作。您正在将 middleware 和 factory 函数混合在一起。
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
)
我正在尝试为 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
参数传递。因此,一旦您 运行 代码并在用户对象不存在时死亡,它就会被调用。即使它没有因此而死,它也不会按预期工作。您正在将 middleware 和 factory 函数混合在一起。
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
)