Итак, после поиска надежного решения безопасности для моего приложения MVC3, я столкнулся с этим сообщением в блоге Риком Андерсоном. В нем описывается подход WhiteList, где пользовательская реализация AuthorizeAttribute применяется как глобальный фильтр, и вы украшаете действия/контроллеры, которые вы хотите разрешить анонимному доступу к использованию фиктивного атрибута AllowAnonymousAttribute (я говорю "фиктивный", потому что внутри AllowAnonymousAttribute нет логики, это просто пустой класс атрибутов)
bool allowAnnonymous = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
if (allowAnnonymous) return;
Это (наряду с другими рекомендациями по безопасности, упомянутыми в его блоге, например HTTPS) дает мне безопасную по умолчанию модель, в которой мне не нужно применять проверку безопасности для каждого отдельного действия и не забывайте также добавлять ее в будущую функцию дополнения.
Первая часть вопроса
Теперь я не использую свойства Users/Roles в AuthorizeAttribute, мне нужно захватить этот материал из базы данных. Для меня это то, что было бы в AuthorizeCore, так как единственная ответственность - вернуть true false, имеет ли пользователь доступ. Однако у меня есть проблема: AuthorizeCore должен быть потокобезопасным, исходя из моего чтения источника для класса AuthorizeAttribute, и я не уверен, что лучший способ обратиться к моей базе данных, чтобы определить права пользователя и придерживаться этого. Мое приложение использует IoC и в настоящее время разрешает моему контейнеру IoC мой репозиторий обрабатывать все это конструктору AuthorizeAttribute, но, делая это, а затем получая доступ к нему в AuthorizeCore, я не создаю проблем с безопасностью потоков? Или будет реализация IoC и MVC3 DependencyResolver, которые я использую для предоставления параметра моему настраиваемому конструктору AuthorizeAttribute, адекватно обрабатывают безопасность потока? Обратите внимание: в моих репозиториях используется шаблон UnitOfWork, который включает в себя мой nHibernate SessionFactory в качестве конструктора для репозитория, а класс Unit of Work предоставляется из моего контейнера IoC, реализованного StructureMap, используя приведенную ниже строку. Правильно ли я рассматриваю используемую здесь область будет обрабатывать проблемы с потоками?
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
Вторая часть вопроса
Моя модель данных (и, таким образом, модель безопасности) настроена так, что мои основные бизнес-объекты определены так, что это одна большая иерархическая модель, и когда я проверяю разрешения, я смотрю в эту модель иерархии, где пользовательская учетная запись была определена и предоставила доступ ко всему, что находится под ней по умолчанию. Проверка вторичных разрешений - это та, которая использует административные разрешения бизнес-логики, подобно тому, как пользователи в роли X получают доступ к функциям "Удалить виджет". Для этого я использую данные маршрута и вытаскиваю имена контроллеров и действий и использую их в сочетании с подробностями из данных основных пользователей для доступа к моей базе данных для разрешения разрешений для этого запроса. Однако эта логика повторяется для каждого ChildAction, используемого на странице, но поскольку я использую имена Controller и Action из данных Route, я фактически не получаю информацию о Child Action. Он остается как имя родительского действия, а не дочернее действие, так как дочернее действие не выполняется с помощью запроса URL. Это приводит к избыточным проверкам безопасности в моей базе данных для получения сведений о родительском действии и ненужных обращениях к ресурсам. При исследовании этого я решил просто обойти проверку безопасности для действий Child и полагаться на родительское действие для этого.
bool bypassChildAction = filterContext.ActionDescriptor.IsDefined(typeof (ChildActionOnlyAttribute), true) || filterContext.IsChildAction;
if (bypassChildAction) return;
Имеет ли смысл делать это, и если так/нет, почему? На мой взгляд, если Action украшен атрибутом ChildActionOnlyAttribute, он недоступен публично через URL-адрес в любом случае. И если он выполняется как действие Child Action, но не является исключительно дочерним действием, я могу обойти проверку безопасности только для этого выполнения, поскольку родительское действие будет обрабатывать разрешения. У вас была бы ситуация, когда вам нужно было бы ограничить доступ к дочернему действию? Зная, что дочерние действия, как правило, очень маленькие частичные представления, я не ожидаю, что это проблема, но я также видел ссылку на строку в реализации по умолчанию OnAuthorization, в которой излагаются некоторые проблемы, связанные с кешированием. Кто-нибудь знает, влияет ли это на мое предложенное решение?
Общие сведения:
- Многопоточные проблемы для доступ пользователя к базы данных в AuthorizeCore
- Проблемы безопасности при обходе Проверка авторизации для дочерних действий.
- Кэширование проблем для дочерних действий сочетается с предыдущей точкой
Любые мнения или помощь в этих аспектах были бы очень благодарны!