Я смотрю на свой дизайн интерфейса и изо всех сил пытаюсь решить, какой самый «правильный» способ реализовать управление доступом на основе ролей, учитывая, что user
и к subject
которому user
хотел бы получить доступ.
Насколько я вижу, у меня есть три основных варианта (четвертый - бастардизация первых трех, а пятый - подстройка четвертого):
- Запрос
subject
со списком разрешений, которыеuser
имеет -subject.allowAccess(user.getPermissionSet)
- Запрос
user
со списком разрешений, которыеsubject
требуются -user.hasPermissionTo(subject.getRequiredPermissions())
- Запрос стороннего, чтобы найти пересечения разрешений -
accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
- Запросить либо
subject
/user
, делегируя «решение» стороннему классу - Иметь
user
попытку доступа кsubject
и выдаст ошибку , если доступ не разрешен
Я склоняюсь к четвертому варианту: « subject
Содержать accessController
поле, в котором содержатся вызовы для subject.userMayAccess(User user)
делегирования операции а-ля:
class Subject {
public function display(user) {
if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
display403(); //Or other.. eg, throw an error..
}
}
}
.. но тогда это вызывает дополнительные вопросы:
- должно
accessController
быть поле против статического класса ..? - Должен ли
subject
знать, какие разрешения требуются для его просмотра? - где здесь действует принцип наименьшего знания в отношении призвания
subject.display()
? Должны ли абонентыsubject.display()
когда-либо знать, что контроль доступа действует? (гдеsubject.display()
последний "шаблонный метод") - есть
subject.display()
управление доступом, выдавая исключение, когда у пользователя нет необходимых разрешений?
Что будет считаться «лучшей практикой» в этой ситуации? Где должна быть ответственность за выполнение проверок?
Так как это в некоторой степени и академическое упражнение, которое затем перейдет к реализации, ссылки на шаблоны проектирования приветствуются.
Я думаю , что ваш вариант 3 является самым близким, но вместо того , чтобы допрашивать
user
иsubject
об их наборах разрешений вы должны пройтиuser
иsubject
к контроллеру доступа.Контроллер доступа должен отвечать как за получение наборов разрешений, так и за проверку достаточности доступа. Таким образом вы изолируете логику хранения и логику проверки в контроллере доступа отдельно от пользователя и субъекта.
Другой элемент, который может отсутствовать в вашем примере, - это какая операция выполняется. Некоторые пользователи могут иметь право читать некоторые данные , но не обновлять, удалять, выполнять и т.д. Таким образом , вы можете иметь
checkAccess
метод на контроллер доступа с тремя параметрами:user
,subject
,operation
. Вы также можете предоставить дополнительную информацию,checkAccess
чтобы получить информацию о том, почему доступ не был предоставлен.Например, делегирование всего этого контроллеру доступа позже позволяет вам заменить способ представления ваших разрешений. Вы можете начать с контроля доступа на основе ролей, а позже перейти к утверждениям на основе утверждений. Для начала вы можете хранить разрешения в простой структуре, а затем добавлять иерархические группы / роли и допустимые операции для различных типов субъектов. Если вы не добавите свои наборы разрешений в интерфейс, это поможет.
На мой взгляд, менее важно, используете ли вы AOP или какой-то стандартный код для подключения.
источник