Действия, разрешения и архитектура - PullRequest
2 голосов
/ 26 февраля 2010

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

Текущий код выглядит примерно так:

public class LogicObject
{
       public void Add()
       {
            Check Add Permission
            Perform
       }
       public void Update()
       {
            Check Update Permission
            Perform
       }
}

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

Другая идея, которая у меня возникла, состояла в следующем:

public class AddAction : IAction
{
   public bool IsPermitted;
   public void Perform();
}

public class LogicObject
{
   public IAction AddAction {get { return new AddAction(); } }
}

Мне больше нравится эта архитектура, но я не совсем настроен на нее. Кажется, немного обманчиво. Я не могу представить, что этот тип архитектуры уникален. Каковы некоторые примеры лучшего способа сделать это?

Ответы [ 3 ]

4 голосов
/ 26 февраля 2010

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

Примером решения для реализации этого для Java является Spring Security , который предоставит вам множество способов настройки и определения вашей схемы авторизации. Объект будет выглядеть примерно так:

public class logicObject {
     @PreAuthorize("hasRole('ROLE_USER')")
           public void update() {
                //Perform
           }

     //...
    }

Конечно, вам понадобится дополнительный код для определения контекста безопасности и создания прокси для класса logicObject с этим контекстом, а также для определения самой авторизации.

Поскольку кажется, что приведенный вами пример кода написан на C #, вам может понадобиться взглянуть на Role Based Security и все товары в пространстве имен [System.Security.Permissions] [2]. Это позволяет использовать атрибуты для контроля доступа метода во время выполнения. Вы можете определить свои собственные атрибуты и поставщика авторизации. Использование может выглядеть примерно так:

public class LogicObject
{
    [PrincipalPermissionAttribute(SecurityAction.Demand, Role="ROLE_USER")]
       public void Add()
       {
            //Perform
       }

}
1 голос
/ 01 марта 2010

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

public class LogicObject
{
       [PrincipalPermission(Security.Demand, Role="AddItem")]
       public void Add()
       {
            Perform
       }
       [PrincipalPermission(Security.Demand, Role="AddItem")]
       public void Update()
       {
            Perform
       }
}

PrincipalPermission проверяет пользователя Thread.CurrentPrincipal, чтобы определить, есть ли у пользователя права на данное действие. Я также создал пользовательские атрибуты, которые имеют схожие функции, но больше касаются безопасности на уровне строк, а не общих прав или разрешений.

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

0 голосов
/ 01 марта 2010

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

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

Я не уверен, что имел место, где находится расширенная документация: блог Тома Холландерса может быть местом для поиска, в противном случае вы можете получить EntLibs от CodePlex.

...