System.Addin - Создание защищенных плагинов ASP.NET MVC
В последнее время я сосредоточился на создании приложения ASP.NET MVC, в котором могут размещаться сторонние плагины MVC. В идеале разработка этих плагинов должна следовать следующим правилам:
- Плагины могут быть разработаны в стандартном проекте MVC и могут использовать всю существующую инфраструктуру инфраструктуры ASP.NET MVC.
- Сложность компиляции проекта MVC плагина и включения его в приложение MVC хоста не должно быть серьезным.
- Любые изменения в нормальном потоке разработки приложения MVC будут минимальным
После некоторого исследования я придумал следующие подходы для достижения этой цели, каждый из которых имеет свои преимущества и недостатки.
Подход 1 - сборка плагина MVC, загруженная в основной домен приложения MVC
Рабочий процесс
- Разработайте плагин внутри отдельного проекта MVC.
- Скомпилируйте сборку и загрузите ее и все зависимости в хост-приложение через
PreApplicationStartMethodAttribute
, MEF или базовая ссылка на сборку в хост-проекте (если это возможно). - Сопоставьте маршрут с контроллерами плагинов, чтобы плагин рассматривался как
Area
внутри хозяина - Поместите виды плагинов в правильную папку области. Файл макета необходимо будет изменить таким образом, чтобы путь макета указывал на местоположение на основе области, а не на корень приложения (что было бы в случае с проектом MVC разработки)
- Когда поступает запрос на плагин, ASP.NET будет использовать функциональность существующих областей, чтобы направить запрос на правильные контроллеры и найти правильное расположение для файлов просмотра.
преимущества
- Будет работать так же легко, как если бы контроллеры были встроены в сборку приложения MVC хоста.
- Просто включить сборки в хост-домен приложения перед запуском приложения (
PreApplicationStartMethodAttribute
, ссылка на проект) и после запуска приложения (MEF)
Недостатки
- Без песочницы - у контроллеров будет тот же уровень доверия, что и у хоста.
Заключение
Это самый простой подход, но он также наименее безопасный. Это по существу исключает возможность создания ненадежными разработчиками плагинов, поскольку эти плагины будут иметь тот же уровень доверия, что и хост-приложение (это означает, что если хост-приложение может выполнять такие методы, как System.IO.File.Delete
так же может плагин)
Подход 2 - сборка плагина MVC, работающая в собственном домене приложений через MAF
Этот подход позволяет создавать плагины MVC, которые можно помещать в свои собственные AppDomains
и используется хостом через System.Addin
библиотеки.
Состав
В хосте настраивается маршрут, который определяет, нацелен ли обрабатываемый URL на плагин. Может иметь такой шаблон, как
example.com/p/{plugin}/{controller}/{action}/{id}
Все маршруты с указанным выше шаблоном сопоставляются с хост-контроллером, который выполняет действие маршрутизации модуля. Это действие просматривает любой данный маршрут и определяет соответствующий плагин для обработки запроса на основе
{plugin}
сегмент.Представление плагина - это объект получателя / отправителя, который действует как шлюз для контроллеров плагина. У него есть метод AcceptRequest, который получает
RequestContext
от хоста, и это возвращаетActionResult
,Плагин конвейера содержит адаптеры, которые могут сериализовать
RequestContext
а такжеActionResult
для передачи через границу изоляции трубопровода.
Выполнение потока
Маршрут для плагина совпадает, и вызывается контроллер маршрутизации плагина.
Контроллер загружает нужный плагин в свой
AppDomain
и вызывает AcceptRequest, проходя черезRequestContext
(который сериализуется через конвейер)AcceptRequest получает контекст и определяет соответствующий контроллер для выполнения на основе этого запроса (используя фабрику пользовательских контроллеров).
Как только контроллер завершил выполнение запроса, он возвращает
ActionResult
к объекту-получателю, который затем передал этоActionResult
(также сериализуется через конвейер) обратно к хостуAppDomain
,Контроллер, который первоначально вызвал AcceptRequest, может затем вернуть
ActionResult
к конвейеру выполнения MVC узла, как если бы он обрабатывал сам запрос. ПлагинAppDomain
затем может быть выгружен, если пожелает.
преимущества
Плагин будет помещен в AppDomain
Таким образом, можно использовать любой набор разрешений, который подходит хосту.
Недостатки
- Должна быть возможность сериализации
RequestContext
а такжеActionResult
, - Возможно, нарушит другие функции ASP.NET MVC в изолированной
AppDomain
,
Заключение
Этот подход звучит хорошо на бумаге, но я не уверен, что возможно / возможно сериализовать RequestContext
а также ActionResult
объекты, а также запустить контроллер MVC в изоляции.
Вопросы
Первый подход хорош, если код создается доверенными разработчиками. Я знаю, что я не собираюсь удалять все файлы представления хоста или его файл web.config. Но, в конечном счете, если вы хотите, чтобы сторонние разработчики создавали плагины для вашего MVC-приложения, вы должны быть в состоянии изолировать их код.
Из всех моих исследований, System.Addin
библиотека облегчает реализацию среды хоста / плагина, когда вы используете простые библиотеки классов на основе API. Однако, кажется, что это нелегко сделать, когда задействован MVC.
У меня есть несколько вопросов:
- Возможен ли второй подход, который я изложил здесь?
- Есть лучший способ сделать это?
- Будут ли в будущем более простые способы изоляции плагинов MVC?
2 ответа
В итоге вы создадите отдельные сайты для каждого плагина. Таким образом, вы можете создавать пользователей с ограниченными правами для каждого AppPool, а системный администратор может установить "плагин" как веб-сайт, работающий под этим пользователем.
Любые альтернативы будут выставлять Антипаттерн Внутренней Платформы. Если у вас не будет много времени и денег, чтобы потратить на разработку системы хостинга плагинов, вы будете увязать в этом и обижаться на него. Я говорю из опыта.
Сайты могут совместно использовать пользовательские репозитории AspnetIdentity, и вы можете предоставить свои основные объекты в виде библиотеки DLL, на которую можно ссылаться. Разместите ваш контент (файлы сценариев, CSS, изображения) в CDN, чтобы на них можно было ссылаться. Если вы хотите поделиться взглядами со своими дочерними сайтами, скомпилируйте их в виде ресурсов:
Включение предварительно скомпилированных представлений в веб-приложение ASP.NET MVC
Удачи!
IMHO System.AddIn немного излишне для того, что вы пытаетесь сделать.
Вы знакомы с пространством имен System.Security.Permissions? Если нет, вы можете взглянуть на FileIOPermission. Возможно, вы могли бы изолировать свою расширяемую систему, используя (и даже не расширяя) механизм безопасности доступа к коду.NET.