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