Лучший способ реализовать детальную авторизацию для веб-приложения? - PullRequest
5 голосов
/ 11 ноября 2008

Я работаю над веб-приложением Rails, и в настоящее время его используют около 20 пользователей.

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

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

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

Я хочу изменить это двумя способами:

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

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

Как вы думаете, какой самый элегантный способ реализовать это?

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

Наконец, вот как это реализовано в настоящее время:

def authorized?
  current_user.role.foo? or current_user.role.bar?
end

А вот моя первоначальная идея, которая, я думаю, не лучший способ решить эту проблему:

+------------+------------+---------+
| department | controller | action  |
+------------+------------+---------+
| accounting | payments   | index   |
| accounting | payments   | new     |
| accounting | payments   | create  |
| accounting | payments   | edit    |
| accounting | payments   | update  |
| accounting | payments   | destroy |
| sales      | payments   | new     |
| sales      | payments   | create  |
| sales      | payments   | edit    |
| sales      | payments   | update  |
+------------+------------+---------+

или

+------------+----------+-------+--------+------+--------+--------+
| department | model    | list  | create | read | update | delete |
+------------+----------+-------+--------+------+--------+--------+
| accounting | payments | TRUE  | TRUE   | TRUE | TRUE   | TRUE   |
| sales      | payments | FALSE | TRUE   | TRUE | TRUE   | FALSE  |
+------------+----------+-------+--------+------+--------+--------+

Ответы [ 3 ]

3 голосов
/ 11 ноября 2008

Базовая концепция авторизации, насколько я понимаю, это роль. Роль может выражать различные вещи:

  1. отношение пользователя к системе в целом (например, быть администратором системы)
  2. отношение пользователя к некоторому виду сущностей (например, быть модератором комментариев)
  3. отношение пользователя к некоторой конкретной сущности (например, быть владельцем какого-либо ресурса)
  4. некоторые другие сложные отношения (например, дружить с пользователем, который является владельцем какого-либо ресурса)
  5. этот пользователь имеет какой-либо атрибут (ы) или он отвечает на какое-то сообщение определенным образом (например, чтобы быть подростком)

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

Другая часть полномочий - это механизм, который решает, какую часть кода запускать (или не запускать), исходя из того, подходит ли пользователь какой-либо роли (набору ролей) или нет. Чтобы применить этот механизм, мы должны найти точки, где должна проходить авторизация, и выбрать роли, для которых должен или не должен выполняться код.

Способ, который работает для меня в Rails, состоит в том, чтобы определить роли на уровне модели и оставить механизм авторизации (установить разрешенные роли для частей кода, которые я хочу авторизовать, и спросить, есть ли у текущего пользователя роль, которой разрешено запустить часть) полностью для контроллеров / представлений.

Для этого я использую твик rails-authorization-plugin, в который встроены все возможности, о которых я только что упомянул (различные виды ролей, множество ролей для одного пользователя, авторизация на контроллере и уровень просмотра).

0 голосов
/ 11 ноября 2008

Из двух ваших предложений первый вариант выглядит немного лучше, поскольку он позволяет вам добавлять действия, которые не могут быть действиями на уровне модели. Я предполагаю, что вы столкнетесь с ситуацией, когда вторая модель не вполне справляется, и вам нужно либо изменить схему, либо начать разбрасывать логику разрешений по всему приложению (например, «Пользователи без доступа« создать ») также не может запустить метод xxx ")

Я думаю, что причина, по которой решение выглядит не очень СУХОЙ, в том, что есть повторение:

  1. В названиях отделов и
  2. В отделе возможностей

Что касается # 1, то имеет смысл создать таблицу отделов и присвоить каждому отделу идентификатор.

Что касается # 2, я согласен с первым комментарием. Вероятно, вы можете сгруппировать различные контроллеры и действия в функциональные группы, а затем установить отношение «многие ко многим» (таблица сопоставления) между пользователями и функциями. Функции тогда будут иметь отношение один ко многим с тем, какие действия / контроллеры они разрешают. Это позволило бы вам с минимальным повторением сказать, что «бухгалтерский учет и продажи должны быть в состоянии прочитать все финансовые таблицы».

0 голосов
/ 11 ноября 2008

вам может понадобиться ввести понятие «функциональные точки» или «функции» в вашу модель в качестве контрольных точек для доступа; «особенность» может иметь необязательную «родительскую особенность» для формирования иерархии. Вы сами решаете, что является, а что нет, и программно проверяете разрешения. Это также должно позволить вам проверять доступ на уровне объектов перед рисованием меню, чтобы пользователи никогда не видели ссылки на страницы, к которым у них нет доступа.

аналогичная ситуация / решение описывается здесь

...