Стандартные практики для контроля доступа (шаблон проектирования)

9

Я смотрю на свой дизайн интерфейса и изо всех сил пытаюсь решить, какой самый «правильный» способ реализовать управление доступом на основе ролей, учитывая, что userи к subjectкоторому userхотел бы получить доступ.


Насколько я вижу, у меня есть три основных варианта (четвертый - бастардизация первых трех, а пятый - подстройка четвертого):

  1. Запрос subjectсо списком разрешений, которые userимеет -subject.allowAccess(user.getPermissionSet)
  2. Запрос userсо списком разрешений, которые subjectтребуются -user.hasPermissionTo(subject.getRequiredPermissions())
  3. Запрос стороннего, чтобы найти пересечения разрешений - accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
  4. Запросить либо subject/ user, делегируя «решение» стороннему классу
  5. Иметь 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()управление доступом, выдавая исключение, когда у пользователя нет необходимых разрешений?

Что будет считаться «лучшей практикой» в этой ситуации? Где должна быть ответственность за выполнение проверок?

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

Kwah
источник

Ответы:

7

Лучше всего использовать так называемый шаблон «Перехватчик» для перехвата вызовов в защищенные зоны.

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

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

Предпочтительно вызывающий абонент и вызываемый абонент не должны знать о доступе, за исключением обработки отказов. Однако проблема будет зависеть от системы, которую вы внедряете, и от того, как вы получаете доступ к учетным данным / принципалу безопасности для вызывающей стороны. Например, в системах SOAP эта информация добавляется в заголовок сообщения SOAP, тогда как в системе Windows она будет доступна через механизм аутентификации Windows.

Если вы используете подход AOP или шаблон перехватчика, он будет выдавать любые необходимые исключения, и клиент (вызывающая сторона) будет обрабатывать любые выданные исключения.

Таким образом вы разделяете ваш клиентский, сервисный и аутентификационный код, не смешивая знания и функциональность.

sweetfa
источник
2

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

class Subject {
    public function display(user) {
        if(!accessController.checkAccess(this, user, AccessControl.Read)) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

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

Другой элемент, который может отсутствовать в вашем примере, - это какая операция выполняется. Некоторые пользователи могут иметь право читать некоторые данные , но не обновлять, удалять, выполнять и т.д. Таким образом , вы можете иметь checkAccessметод на контроллер доступа с тремя параметрами: user, subject, operation. Вы также можете предоставить дополнительную информацию, checkAccessчтобы получить информацию о том, почему доступ не был предоставлен.

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

На мой взгляд, менее важно, используете ли вы AOP или какой-то стандартный код для подключения.

Рори
источник