Подтвердить что ты не робот

Метод авторизации на основе групп/правил в node.js и express.js

Каковы хорошие стратегии для авторизации на основе ролей в express.js? Особенно с экспресс-ресурсом?

С Express-resource никаких обработчиков нет, поэтому я думаю, что есть три варианта:

  • Использовать промежуточное программное обеспечение
  • Передайте функцию авторизации ресурсу и проверьте каждый запрос ресурса отдельно
  • Проверить авторизацию с каждым запросом сразу после аутентификации

Есть ли другие решения?

Авторизация на основе групп/ролей - довольно античный подход. Существуют ли новые методы контроля доступа? Если нет, как можно применить авторизацию на основе ролей к node.js? Где хранить отношения группового правила (с NoSQL/CouchDB/Redis)?

В качестве примера, структура:

/
  /forums
    /forums/threads

Каждый ресурс с индексом, новым, создаёт, показывает, редактирует обновление и уничтожает. Некоторые люди могут редактировать/удалять и т.д. Темы и форумы, некоторые люди не должны.

4b9b3361

Ответ 1

Connect-role довольно хороший, простой и документация тоже очень понятная.

var user = roles;

app.get('/profile/:id', user.can('edit profile'), function (req, res) {
  req.render('profile-edit', { id: req.params.id }); 
})
app.get('/admin', user.is('admin'), function (req, res) {
  res.render('admin');
}

Ответ 2

Я бы сказал, что это сложно решить с помощью экспресс-ресурса, поскольку он не позволяет использовать связующее ПО, специфичное для маршрута (по крайней мере, не в чистом виде). ​​

Я бы выбрал аналогичный макет, как модуль экспресс-ресурсов, но проложил его с помощью обычного старого экспресса. Что-то вроде этого:

// Resource
var forum = {
  index: // ...
  show: // ...
  create: // ...
  update: // ...
  destroy: // ...
};

// Middleware
var requireRole = function(role) {
  return function(req, res, next) {
    if('user' in req.session && req.session.user.role === role)
      next();
    else
      res.send(403);
  }
};

// Routing
app.get('/forums', forum.index);
app.get('/forums/:id', forum.show);
app.post('/forums', requireRole('moderator'), forum.create); // Only moderators can create forums
app.delete('/forums/:id', requireRole('admin'), forum.destroy); // Only admins can delete forums

ОБНОВЛЕНИЕ:. Продолжались обсуждения относительно промежуточного ПО, специфичного для маршрута, в экспресс-ресурсе, например. здесь. По-видимому, преобладающее представление состоит в том, чтобы иметь массив для каждого действия, например:

var forums = {
  index: [ requireRole('foo'), function(req, res, next) { ... } ]
};

Вы можете просмотреть запросы на растяжение и посмотреть, есть ли что-нибудь, что вы могли бы использовать. Конечно, я полностью понимаю это, если вам это не нравится. Я уверен, что в будущем мы увидим что-то подобное в экспресс-ресурсе.

Единственное другое решение, о котором я могу думать, - это ответ на вопрос Джона Джунгбома, который должен был собрать ресурсы с помощью экспресс-ресурса, но у него есть "внешнее" связующее ПО, что-то вроде:

app.delete('*', requireRole('admin')); // Only admins are allowed to delete anything
app.put('/forums/*', requireRole('moderator')); // Only moderators are allowed to update forums

Но я сожалею, что это утечка URL-адресов повсюду.

Ответ 3

Я изучаю тот же вопрос и сталкиваюсь с несколькими хорошими модулями. Я сосредоточен на пакете node -acl, который можно найти здесь. https://github.com/optimalbits/node_acl.

Этот пакет, по-видимому, реализовал шаблон ACL очень понятным образом и предоставил способы легко интегрировать его в ваше приложение node/express.

Во-первых, вы захотите определить свои ресурсы, роли и разрешения.

Например, ресурсы могут быть:

/
  /forums
    /forums/threads

Роли могут быть

public
admin
user
   john
   jane

В этом примере роли john и jane могут сопоставляться с реальными учетными записями пользователей, но они наследуют все разрешения пользователя.

Права на ресурсы

  • создать
  • Показать
  • update
  • уничтожить

Или ваши стандартные операции CRUD.

Теперь, когда они были определены, мы можем взглянуть на то, как это будет выглядеть для установки acl с помощью node -acl. Эти примечания получены из документации

импортировать пакет

var acl = require('acl');

Настройте свой сервер. Мое приложение использует mongodb, но пакет node -acl поддерживает другие механизмы хранения

acl = new acl(new acl.mongodbBackend(dbInstance, prefix));

Мое приложение использует mongoose, поэтому dbInstance будет заменен mongoose.connection.db

Теперь добавим наши роли в ACL. В node -acl роли создаются путем предоставления им разрешений. Это похоже на убийство двух зайцев одним камнем (ни один из птиц не пострадал)

acl.allow('admin', ['/', '/forum', '/forum/threads'], '*');
acl.allow('public', ['/', '/forum', '/forum/threads'], 'show');
acl.allow('user', ['/', '/forum', '/forum/threads'], ['create', 'show']);

Предположим, что новый ресурс создан john, мы добавим новую запись, которая позволит john также обновлять и удалять этот ресурс.

acl.allow('john', ['/forum/threads/abc123'], ['update', 'delete']);

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

В большинстве экспресс-конфигураций это выглядит как pos

app.post('/', acl.middleware(), function(req, res, next) {...});
app.post('/forums', acl.middleware(), function(req, res, next) {...});
app.post('/forums/:forumId', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads/:threadId', acl.middleware(), function(req, res, next) {...});

Если параметры не переданы, это проверяет, разрешена ли роль, определенная в req.userId, выполнять метод http на идентифицированном ресурсе, но маршрут.

В этом примере метод http - это сообщение, но он будет делать то же самое для каждого http idenitified в вашей конфигурации.

Возникает вопрос о разрешениях, определенных ранее. Чтобы ответить на эти вопросы, нам нужно было бы изменить разрешения от

  • создать
  • Показать
  • update
  • уничтожить

К обычным

  • после
  • получить
  • поместить
  • удалить

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

Мне нравится подход плагинов node -acl, так как он позволяет назначать очень мелкие грань разрешений с использованием очень простого и гибкого api. В их документации гораздо больше, мой пример показывает, что я с пакетом.

Надеюсь, это поможет.

Ответ 4

В express вы можете добавить обработчик, который подключается к каждому оператору (http://expressjs.com/guide.html#passing-route control), где вы можете сделать предварительную проверку. Здесь вы можете получить роль для пользователя и ограничить доступ на основе HTTP-глагола (PUT, DELETE и т.д.) Или URL-адреса (param('op') is "edit" или так).

app.all('/user/:id/:op?', function(req, res, next){
  req.user = users[req.params.id];
  if (req.user) {
    next();
  } else {
    next(new Error('cannot find user ' + req.params.id));
  }
});

Ответ 5

Я написал модуль как неявное промежуточное ПО маршрутизации. Хорошо работает с экспресс-маршрутами.

Gandalf on GitHub

Ответ 6

Вы можете попробовать Casbin: https://casbin.org/, у него есть версия Node.js. Он также имеет промежуточное программное обеспечение Express.js под названием express-authz: https://casbin.org/docs/en/middlewares