2015-05-25 2 views
0

Я пытаюсь написать очень простой компонент промежуточного программного обеспечения для 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), чтобы выяснить, является ли или не содержать разрешенные роли пользователя, присваиваемый роль.

Однако, когда я это делаю, я получаю 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

Можете ли вы показать нам, где вы добавляете к промежуточному? Если бы я должен был предположить, что вы добавляете его как 'authorize()' вместо 'authorize'. –

+0

@BenjaminGruenbaum У меня есть обновленный мой вопрос. Как вы думаете, мне нужно передать все параметры (т. Е. Req, res, next) в мое промежуточное ПО в маршрутизации, чтобы заставить это работать? Спасибо за вашу помощь – nmagerko

+1

Нет, вам нужно передать _a function_ внутри, а не называть его, если это слишком абстрактно для вашего текущего JS - оберните его в (function() {return authorize (....);}) –

ответ

1

При регистрации маршрута с

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

метод authorize запускается на выполнение сразу по authorize(...) с ['ADMINISTRATOR', ...] массив передается в качестве параметр req. Следовательно, он вызывается, как только вы запускаете код и умираете на объекте пользователя, который не присутствует. Даже если бы он не умер на этом, это не сработало бы по назначению. Вы смешиваете промежуточное ПО и фабрику работают вместе.

Express middleware является функцией с подписью (req, res, next), что вы не выполняете себя. Вам нужно пройти ссылку такой функции промежуточного программного обеспечения и Экспресс сама выполняет его по требованию, когда это необходимо, а именно:

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

параметризованным функция промежуточного слоя, как в вашем случае, может быть легко создан раскалывается на заводе и промежуточного функции:

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

Очень подробно объяснено. Надеюсь, что это поможет кому-то, кроме меня! – nmagerko

Смежные вопросы