Как реализовать систему разрешений, которая зависит от значений, которые пользователь пытается сохранить?

Контекст представляет собой систему управления образованием, построенную на Zend Framework. Мы реализуем RESTful MVC для обработки практически всех взаимодействий данных с клиентами. Отношения между ресурсами отображаются в базе данных с помощью внешних ключей и т. д.

Пример: учитель создает отчет по конкретному ученику.

В настоящее время у нас есть система разрешений на основе ролей, которую можно адаптировать к уровню отдельной роли (используя, например, teacher_5 в качестве имени роли). Поэтому мы можем легко ограничить доступ к уже существующему отчету (путем создания разрешений в модели отчета, которая позволяет редактировать/устанавливать разрешения на отчет только для роли наставника, создавшего его, скажем). Проблема возникает при создании. Чтобы добавить отчет, пользователь может разместить в /reports, например, следующие данные:

{ achievement: "4", performance: "5", student_id: "10" }

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

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

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

if ($acl->isAllowed($resource, $role, $action, $field, $value))

где $resource будет моделью отчета, $role будет учителем teacher_5, $action будет "сообщением", $field будет student_id, а $value будет 10. Класс acl, по сути, будет обрабатывать вызов самого $resource.

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


person kasimir    schedule 14.05.2012    source источник
comment
Вы видели Zend ACL Утверждения уже есть? Я использую их в таких ситуациях, как ваша, когда существует более сложная логика, связанная с предоставлением/отказом в доступе. Это может быть то, что вы ищете.   -  person drew010    schedule 14.05.2012
comment
draw010: Вот что я бы использовал ;)   -  person Tomáš Fejfar    schedule 14.05.2012
comment
Спасибо @ drew010. Я смотрел на это некоторое время назад... Я думаю, что отклонил его, потому что в настоящее время я использую объект ресурса по умолчанию. Будет ли идея заключаться в том, чтобы я реализовал Zend_Acl_Resource_Interface в своих моделях, а затем в самом утверждении вытащил бы из модели соответствующие детали и внедрил бы там логику? Кроме того, утверждения применяются только в том случае, если они возвращают истину, поэтому мне пришлось бы добавить отдельные правила отказа и разрешения для каждого действия. Но в таком случае, какой из них имеет приоритет?   -  person kasimir    schedule 15.05.2012
comment
Сказав это, я предполагаю, что правило утверждения может просто передать метод isAllowed в модели, и правило разрешения вернет isAllowed, в то время как правило отказа вернет !isAllowed, и тогда не может быть путаницы.   -  person kasimir    schedule 15.05.2012
comment
@kasimir Может быть немного сложно разобраться в вашем конкретном случае, но я использовал утверждения, чтобы делать некоторые интересные вещи. Вы можете использовать утверждения даже без определенной роли или ресурса, как показано с помощью CleanIP_Assertion в руководстве ZF. Я не уверен на 100%, но я считаю, что утверждение проверяется только в том случае, если роль может получить доступ к запрошенному ресурсу и привилегии, поэтому, если ни одно из них не соответствует действительности, нет необходимости проверять утверждение. По сути, я использовал утверждение, чтобы еще глубже изучить вошедшего в систему пользователя (независимо от роли), и использовал утверждение, чтобы решить, может ли пользователь   -  person drew010    schedule 16.05.2012
comment
...доступ к запрошенной функции. Это может не сработать в вашем случае, но я решил, что не нужно иметь дополнительный уровень логики/управления, который вы должны запрашивать в дополнение к ACL, было бы хорошо. Но, надеюсь, вы сможете проявить творческий подход к утверждениям и найти способ сделать то, что вы пытаетесь сделать.   -  person drew010    schedule 16.05.2012
comment
Решение в этом направлении возможно в моем случае, только слегка изменив Zend_ACL, чтобы разрешить или запретить утверждения, а не правила для реализации разрешения или запрета. Однако у этого метода были очень серьезные проблемы с производительностью, и мы собираемся пойти по другому пути, включающему определение абстракций более высокого уровня, которые представляют свойства ресурса, которые представляют интерес для ACL, а затем реализацию кеша. .   -  person kasimir    schedule 01.06.2012
comment
Я предполагаю, что связь между учеником и учителем определена где-то еще, поэтому вы можете (1) создать экземпляр объекта динамического утверждения, внедрив соответствующий объект сопоставления/доступа к данным (2) реализовать метод assert() для объекта динамического динамического утверждения, используя картограф для проверки ассоциации ученик/учитель (3) Отметьте $acl->isAllowed() в контроллере. Не кажется чрезмерно требовательным к производительности, поскольку проверка будет выполняться только тогда, когда вам это нужно.   -  person David Weinraub    schedule 24.06.2012


Ответы (1)


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

person Community    schedule 26.06.2014