Подтвердить что ты не робот

Внедрение ненадежных плагинов в веб-приложении .NET

Я хотел бы разработать приложение, которое принимает плагины из сообщества пользователей, подобно тому, как это делает Chrome или Firefox. Это будет веб-приложение, поэтому каждый "экземпляр" приложения для отдельных пользователей будет запускать разные плагины (плагины будут загружаться как отдельные экземпляры, но будут "активны" только для определенных пользователей). Я планирую реализовать приложение в .NET и попытаюсь создать архитектуру для модели плагина.

Вот мои желаемые атрибуты:

  • Плагины создаются полностью вне моего основного приложения, как отдельные сборки.
  • Плагины запускаются в своей собственной "заблокированной" среде с низким доверием. Возможно, отдельный AppDomain.
  • Плагины могут работать только через API, который я предоставляю. Например. Я передам им какой-то фасад в качестве интерфейса, и они могут только называть это, а не звонить на любые другие сборки. У меня не может быть плагинов, которые могут произвольно предпринимать действия на веб-сервере, например. влияют на файловую систему.
  • Неудачный сбой в аддине не может повлиять на стабильность основного приложения.

Кажется, что System.AddIn - моя лучшая ставка, но я не понимаю, как заставить загруженные аддины работать только через API, который я предоставляю, и не загружать другие сборки. Предоставляет ли System.AddIn эту функциональность? Кроме того, можно ли использовать System.AddIn с ASP.NET/IIS?

Какие еще параметры у меня есть, кроме System.Addin?

4b9b3361

Ответ 1

Вы можете попробовать использовать AppDomains и обрабатывать необработанные исключения. Чтобы избежать сбоев приложений, вам придется обрабатывать AppDomain.UnhandledException

В приведенной выше ссылке обратите внимание на следующее утверждение

Начиная с .NET Framework 4, это событие не возникает для исключений, которые повреждают состояние процесса, например переполнение стека или нарушения доступа, если обработчик событий не критичен с точки зрения безопасности и имеет атрибут HandleProcessCorruptedStateExceptionsAttribute.

Поэтому вам может потребоваться явно обработать некоторую конфигурацию.

Я прочитал много проблем, утверждая, что, когда необработанные исключения происходят в разных потоках дочернего домена, пузырь вверх и сбрасывает родительский домен. Если это так, то рекомендуется загрузить все плагины в отдельный процесс с помощью приложения для каждого плагина или загрузить плагины в отдельный процесс.

Я также наткнулся на следующий вопрос о SO, который, я считаю, вы найдете очень полезным

Ответ 2

Похоже, ваша главная проблема - это изоляция (как для безопасности, так и для надежности).

Таким образом, ваш лучший вариант - активировать ваш addin в отдельном AppDomain. В этом домене вы можете контролировать, какие сборки вы могли бы загрузить (см. Класс AppDomainSetup).

Ваш основной код также будет защищен от любых неприятных происшествий внутри плагина. Все методы плагина должны будут работать с копиями основных объектов (если только объекты, которые вы передаете, наследуются от MarshalByRefObject, и в этом случае все ставки выкл). Исключения из методов addin можно обрабатывать путем переноса всех вызовов в try за исключением или через событие AppDomain UnhandledExcption.

Имейте в виду, что существует ограничение производительности для пересечения границ AppDomain. Вызов по сути является удаленным вызовом.

Еще одна потенциальная проблема заключается в том, как вы планируете управлять AppDomains. Я никогда не пытался создать несколько процессов AppDomains в процессе, но я ожидал бы неприятностей здесь. Объединение Addins для нескольких пользователей в одном домене wold вызовет защиту, которую вы пытаетесь встроить в этот

В ответ на вопрос @RationalGeek - Событие UnhandledException позволяет сделать это - вроде. Вы можете подписаться на это событие как в своем ключевом домене, так и в домене плагинов, но есть много неопределенностей в этом отношении - см. Статью, на которую я ссылался для более подробной информации. Может быть лучшим вариантом было бы обернуть каждый вызов вашего API в try/except

Ответ 3

Почему бы просто не использовать отражение и обнаружить доступные плагины во время выполнения? Assembly.LoadFile, чтобы получить сборку, GetExportedTypes для получения ваших объектов Создайте экземпляр с Activator.CreateInstance

Затем просто запустите плагин в цикле try, чтобы убедиться, что он не влияет на систему. Хотя для обеспечения реальной стабильности вам понадобится значительная архитектура.

Держитесь подальше от MEF, если у вас нет сложных сценариев для управления подключаемыми модулями. Если он просто позволяет пользователям использовать их и включать в себя несколько своих собственных, просто используйте отражение.