Подход на основе групп / правил авторизации в node.js и express.js - PullRequest
22 голосов
/ 22 февраля 2012

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

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

  1. Использовать промежуточное ПО
  2. Передать функцию авторизации ресурсу и проверить каждый запрос ресурса отдельно
  3. Проверять авторизацию с каждым запросом сразу после аутентификации

Существуют ли другие решения?

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

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

/
  /forums
    /forums/threads

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

Ответы [ 6 ]

32 голосов
/ 28 февраля 2012

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

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

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

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

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

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

Единственное другое решение, которое я могу придумать, - это ответ Яна Чонбума, который будет заключаться в монтировании ресурсов с помощью express-resource, но с промежуточным программным обеспечением, подключенным «вне» этого, что-то вроде:

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

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

27 голосов
/ 05 февраля 2014

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

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

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

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

/
  /forums
    /forums/threads

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

public
admin
user
   john
   jane

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

Разрешения на ресурсы

  • создать
  • шоу
  • обновление
  • уничтожить

Или ваши стандартные операции 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']);

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

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 является post, но он будет делать то же самое для каждого http, идентифицированного в вашей конфигурации.

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

  • создать
  • шоу
  • обновление
  • уничтожить

К обычному

  • сообщение
  • получить
  • 1074 * ставить *
  • удалить

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

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

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

12 голосов
/ 10 июня 2013

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');
}
3 голосов
/ 22 февраля 2012

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

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));
  }
});
2 голосов
/ 14 марта 2012

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

Гэндальф на GitHub

0 голосов
/ 11 мая 2019

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

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