Как вы вплетаете аутентификацию, роли и безопасность в свой DDD?

Как вы реализуете роли и безопасность в своих проектах C# Domain Driven Design? У нас ведутся споры о том, должно ли оно быть реализовано в вызывающем приложении (ASP.NET MVC) или в самой модели предметной области (объекты и службы модели). Некоторые утверждают, что это должно быть на самом веб-сайте, поскольку там уже существует аутентификация. Но это означает, что каждый раз, когда вы интегрируетесь с основными бизнес-системами, вам придется заново реализовывать систему безопасности.

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

Кстати, вот хороший тезис на эту тему, который охватывает 7 различных сценариев, касающихся DDD и безопасности:

Безопасность в доменно-ориентированном проектировании

  • Chapter 4 Security service design scenarios
    • 4.1 Scenario 1: Security service as regular service
    • 4.2 Сценарий 2: Безопасность, встроенная в пользовательский интерфейс
    • 4.3 Сценарий 3. Служба безопасности, инкапсулирующая модель предметной области
    • 4.4 Сценарий 4: Служба безопасности как шлюз для пользовательского интерфейса
    • 4.5 Сценарий 5: Служба безопасности как адаптер для пользовательского интерфейса
    • 4.6 Сценарий 6: Служба безопасности, интегрированная АОП с адаптерами
    • 4.7 Сценарий 7: Служба безопасности интегрирована с АОП

Я лично склоняюсь к АОП с использованием PostSharp, но, поскольку я мало что делал с ним раньше, я не решаюсь сделать прыжок.


person Todd Smith    schedule 20.05.2009    source источник
comment
Вау, PostSharp выглядит круто, я о таком раньше не слышал.   -  person D'Arcy Rittich    schedule 21.05.2009
comment
Для меня варианты, представленные в этой ссылке на документ, являются лучшим ответом на этот вопрос. Мне нравится сценарий в разделе 4.3.   -  person atconway    schedule 14.02.2013
comment
Могу ли я спросить, есть ли более подробная информация о реализации этой интересной диссертации на Gitup?   -  person Anyname Donotcare    schedule 13.10.2018


Ответы (1)


Не забывайте, что во время выполнения уже встроена абстрактная система безопасности/пользователя - принципал (см. >существующий ответ — обратите внимание, что GenericIdentity — это только один вариант; написать свой собственный довольно просто).

Ваш пользовательский интерфейс может обрабатывать создание и назначение участника на основе конкретной реализации (действительно, IIRC ASP.NET и WCF делают это автоматически, или для winforms/wpf вы можете использовать идентификатор Windows или (через веб-службу) тот же ASP вход в .NET).

Затем ваша бизнес-логика просто проверяет Thread.CurrentPrincipal; отсюда вы можете получить имя, метод аутентификации и проверить наличие ролей (без необходимости знать, как реализованы роли).

Среда выполнения также предоставляет встроенные проверки:

    [PrincipalPermission(SecurityAction.Demand, Role = Roles.Admin)]
    public void Foo() {...}

(где Roles.Admin — строковая константа имени вашей роли) Это автоматически проверит доступ, выдав SecurityException, если не в роли. Вы также можете проверить через код (полезно, если роль не фиксируется во время компиляции).

Очевидно, что ваш пользовательский интерфейс должен проверять роли (чтобы отключить/скрыть функциональность), но хорошо иметь бизнес-код, который применяет роли без необходимости знать о пользовательском интерфейсе.

(добавлен)

Я должен упомянуть, что GenericIdentity удобен для модульных тестов. Конечно, вы можете создать собственный API безопасности, и никто вас не остановит...

person Marc Gravell    schedule 20.05.2009
comment
Что мешает пользователю создать свой собственный URL-адрес /Order/Delete/42, если он не является владельцем этого конкретного номера заказа? Я понимаю ограничение доступа на основе ролей, но это не распространяется на владение, не так ли? - person Todd Smith; 21.05.2009
comment
На самом деле это не так (само по себе); вам нужно будет выбрать роль на основе данных отдельного запроса. - person Marc Gravell; 21.05.2009
comment
Таким образом, в дополнение к авторизации роли, предоставляемой чем-то вроде атрибута PrincipalPermission, мне все равно нужно будет выполнить проверку владения, например if (!order.IsOwnedBy (User.Identity.Name)) {throw} ? - person Todd Smith; 26.05.2009
comment
Да, я думаю, что это справедливо, хотя, возможно, if(!order.IsOwnedBy(...) && !UserUtility.IsInRole(Roles.SUPER_ADMIN)) {throw} для учета таких вещей, как доступ администратора. - person Marc Gravell; 26.05.2009