Шаблоны управления доступом - PullRequest
5 голосов
/ 17 декабря 2009

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

Скажем, у меня есть «Класс обслуживания»

abstract class Service {


}

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

class Companies extends Service {

  function getCompanyInfo($id) {
      //...
  }

}

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

На данный момент я могу реализовать это следующим образом:

  1. Добавить accesscontrol в класс Service. Каждый метод (например, getCompanyInfoById) должен вызвать метод hasPrivilege внутри, прежде чем завершить операцию и вернуть результат.
  2. Обернуть все объекты Service в некоторый вид объекта Proxy, который проверяет привилегии перед вызовом метода во внутреннем объекте.
  3. Полностью разделите управление доступом и заставьте «вызывающего» проверить привилегии перед вызовом метода.

Минусы для каждого варианта:

  1. Это требует изменения всех Сервисов, и требует, чтобы они знали Контроль доступа. Я чувствую, что это идет против разделения интересов.
  2. Это нарушает функции ООП, такие как Полиморфизм. Звонящий больше не знает какие интерфейсы любой сервис поддерживает.
  3. Это наиболее гибкий, но большой недостаток в том, что проверка разрешения теперь неявна. Разработчики могут «забыть», или сложные пути кода могут вызывать несанкционированные сервисы.

Есть ли лучшие способы подойти к этому вообще?

Ответы [ 3 ]

3 голосов
/ 17 декабря 2009

Другим решением может быть маленький вариант вашего 1.

ех.

class Service
{
  var $ACL = //some hash map with acl
}

class Companies extends Service
{

  function getCompanyById($id)
  {
    //real code
  }
}

class SafeCompanies extends Companies
{
//If a method must be "protected" with an ACL, you must override them in this way
  function getCompanyById($id)
  {
    $this->check('read'); //raise an exception if current user haven't READ privilege
    parent::getCompanyById($id);    
  }  
} 

таким образом вы не смешиваете обязанности и все еще можете использовать полиморфизм

мои 2 цента

3 голосов
/ 17 декабря 2009

Модель Java EE в значительной степени соответствует строкам 2. Ваш код выполняется в «контейнере», вы сообщаете контейнеру о точках входа интерфейса (URL-адреса для сервлетов, методы для EJB) и определяете роли, которые можно использовать эти точки входа. Администратор сопоставляет информацию аутентификации (например, пользователя и группы LDAP) с конкретными ролями, и контейнер обращается к этому сопоставлению при предоставлении доступа к точкам входа.

Ключевым моментом здесь является то, что Контейнер "знает" о вашем коде, это фактически довольно умный прокси.

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

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

0 голосов
/ 07 июня 2019

Десять лет спустя ... С тех пор мир эволюционировал совсем немного, и, в частности, возникла совершенно новая парадигма: внешняя авторизация. Чтобы быть справедливым, каждая среда разработки имеет свою собственную версию (например, CanCanCan в Ruby или Spring Security в Java или авторизация на основе утверждений в C #). Внешняя авторизация направлена ​​на отделение логики авторизации от бизнес-логики. Идея заключается в том, что потребности в авторизации могут развиваться независимо от бизнес-логики. Например, ваша бизнес-логика обеспечивает доступ к банковским счетам (просмотр / редактирование / удаление / перевод). Функциональность стабильна - она ​​не изменится в ближайшее время. Однако потребности в авторизации могут изменяться из-за законодательства (GDPR, Open Banking ...) или других требований (делегирование, родитель-ребенок, VIP ...). Вот почему вы хотите сохранить авторизацию внешне .

Для этого существует модель под названием управление доступом на основе атрибутов (), которая является развитием / расширением более известного управления доступом на основе ролей ( ). В RBAC управление доступом ориентировано на идентичность. Он основан на пользователе, роли и группах, к которым принадлежит пользователь. Это не достаточно часто раз. В ABAC вы можете использовать атрибуты пользователя, ресурса, контекста (времени) и действия. ABAC также позволяет писать политики на простом старом английском языке, используя стандартные языки политик ( или или Rego). Облачные платформы (AWS и Google) также реализовали свой собственный язык (называемый Google IAM и AWS IAM соответственно).

Некоторые из преимуществ ABAC:

  • гибкость: вы можете изменить политику авторизации, не касаясь приложений / API
  • возможность повторного использования: вы можете применять те же политики к данным, API, приложениям или инфраструктуре.
  • видимость: выражайте авторизацию в виде политик, а не жестко кодируйте логику, что означает, что вы можете легко проводить аудит политик и понимать, что возможно / что нет
  • проверяемость: с ABAC вы получаете единый журнал всех предоставленных или запрещенных прав доступа.

Если вы хотите узнать больше, посетите страницы Википедии для ABAC и ALFA , а также NIST на ABAC .

.
...