Node.js: авторизация маршрутов и авторизация методов - PullRequest
0 голосов
/ 26 июня 2018

Быстрый фон

Я создаю API с Node.js, Express и Mongoose.Реализованная мною аутентификация работает с пакетом passport-headerapikey.Я ищу пользователя в базе данных с помощью API-ключа и добавляю этого пользователя в объект req.Таким образом, обеспечивая мои знания о личности все время, пока не закончится запрос.

Авторизация

Давайте перейдем к вопросу.

До сих пор я звонил authorize() function вкаждую конечную точку вручную, прежде чем делать что-либо.Вот так:

router.post('/', (req, res) => {
  autorize('admin', req.user.role) // method is called at every route manually
    .then(() => {
      ... do stuff here 
    })
    .catch(err => req.status(403).send())
}

Мой коллега сказал мне, что это не очень хорошее решение, и вместо того, чтобы просто защищать конечную точку, мне нужно иметь управление сеансом, которое делает текущего пользователя доступным глобально, чтобы я могавторизовать в любой точке каждую функцию индивидуально.

Значение: Метод createUser(obj) может затем вызвать внутри себя метод авторизации или проверить условие следующим образом:

createUser(obj) {
  if (currentUser.role !== 'admin') {
    return false        
  }

  obj = new User(obj)
  return obj.save()
}

Это означало бы, что я буду return false в каждой функции, если выполнено условие.Доступ к глобально доступному currentUser для этого сеанса.(например, globalCurrentUser.role !== admin или что-то в этом роде)

Мой вопрос (ы)

  1. Это плохая практика - просто защищать конечные точки, а не функции?
  2. Разве я не могу просто потребовать дополнительный параметр "auth" для каждой функции, чтобы при вызове ей нужно было получить currentUser.role, как в моей authorize() функции, или он возвращает false?Это означает, что я передаю пользователя вручную каждой функции, или она просто не будет работать
  3. Если мне нужно иметь управление сеансами для глобального доступа пользователя во время запроса: у вас есть предложения по инфраструктуре?

Заранее спасибо, Бенно

1 Ответ

0 голосов
/ 26 июня 2018

Аутентификация и авторизация - две разные вещи и должны рассматриваться отдельно. Аутентификация говорит "кто ты?" и авторизация говорит "у вас есть разрешение?" Учитывая, что Express разработан исключительно для промежуточного программного обеспечения, я бы сделал следующее.

  1. Абстрагируйте вашу аутентификацию в единый промежуточный компонент, который будет работать для всех ваших конечных точек, используя app.use() перед монтированием маршрутизатора / маршрутов.
  2. Создайте функцию авторизации, которую можно вызывать из любого места, она принимает пользователя (или идентификатор или что-то еще у вас) и роль, а затем проверяет, есть ли у пользователя эта роль.

Думайте об этом так, ваша авторизация никогда не изменится, она является основой вашего приложения. Если вы решили отказаться от Expressjs и использовать Koa или перейти от традиционных HTTP-запросов к веб-сокетам, вы не захотите менять логику авторизации. Но ваша аутентификация может измениться, вы можете больше не использовать заголовок для хранения токена, возможно, вы переключаетесь на куки или что-то другое, вы можете изменить это.

В итоге вы получите глобальную промежуточную программу, которая проверяет токен аутентификации и присоединяет объект user к req. Тогда у вас будет служебная функция, которая называется что-то вроде userHasRole, которая будет вызываться на любой конечной точке, которая требует определенной роли в приложении. Теперь вы можете проверить разрешения в любой точке приложения. Это может происходить в самых разных местах вашего приложения, например, вы можете проверить, являются ли они администраторами в начале запроса к некоторой панели администратора, но вы можете проверить разрешения позже, если они попытаются получить доступ к определенному ресурсу. При доступе к определенному ресурсу вы можете пропустить их и в последний момент определить, имеют ли они доступ к ресурсу. (Трудно привести конкретный пример, не зная больше о вашем приложении).

В некоторых случаях может быть целесообразно проверить в начале бизнес-логики, в других местах имеет смысл проверить позже. Это не должно иметь значения, вы должны быть в состоянии выполнить эту проверку, когда вам нужно. Это будет полностью зависеть от бизнес-логики, и размещение ее в каждой отдельной функции может оказаться бесполезным, если оно просто форматирует строковый вывод, но может оказаться полезным при попытке извлечь запись из БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...