Предположим, у меня есть ASP.NET MVC webapp, который вызывает слой репозитория, который построен поверх nHibernate. Контроллер передает репозиторию ISecurityToken
, который инкапсулирует идентификатор и разрешения текущего пользователя, а репозиторий использует его при запросе только для возврата строк, которые пользователь должен уметь видеть.Куда должна идти логика безопасности?
Я хочу, чтобы сущность (билет) была закрыта только определенной группой пользователей, а также пользователю, которому назначен билет. Другими словами, гипотетическая CanCloseTicket()
метод требует два входа:
- сам (или его нынешний владелец ID) билет
- текущего пользователя
ISecurityToken
Где должен этот гипотетический метод жить? Я вижу несколько возможностей, но у каждого есть свои недостатки.
- В контроллере: Контроллер имеет доступ ко всему, что необходимо, но это позволяет избежать обхода защиты. («К сожалению, я забыл вызвать CanCloseTicket() в этом действии, прежде чем установить
ticket.IsOpen
в false!» Это плохо пахнет. - В репозитории: репозиторий также имеет доступ к обоим частям, но мне также необходимо сделать
Ticket.IsClosed
, чтобы остановить то же самое, что и раньше. Репозиторий живет в совершенно другой сборке, чем в модели, поэтому использование внутренних сеттеров не будет работать. Вместо этого я мог оставить публичный сеттер и сравнить текущее значение свойства с его оригинальным один, возвращая ошибку, если непривилегированный пользователь закрывает его, но это также немного пахнет мне. («Ой, я забыл проверить возвращаемое значениеrepo.CloseTicket()
в этом методе действий!») - В билете: добавление
Ticket.Close(ISecurityToken token)
и заставляя субъект, ответственный за свою собственную логику безопасности, чувствует себя ke Нарушение SRP.
Я думаю, что хранилище является лучшим вариантом здесь, но он чувствует себя более как наименее худший вариант. Есть ли еще что-нибудь?
Какие еще обязанности есть у класса `Ticket`? – 2010-12-10 14:05:10