在.NET Web应用程序中实现不受信任的插件

时间:2013-04-01 12:26:28

标签: .net plugins architecture add-in

我想开发一个接受用户社区插件的应用程序,类似于Chrome或Firefox的插件。这将是一个Web应用程序,因此单个用户的应用程序的每个“实例”将运行不同的插件(插件将作为单例实例加载,但仅对某些用户“活动”)。我计划在.NET中实现该应用程序,并试图为插件模型提出一个架构。

以下是我想要的属性:

  • 插件完全在我的核心应用程序之外构建,作为单独的程序集。
  • 插件运行在他们自己的“锁定”,低信任环境中。可能是一个单独的AppDomain。
  • 插件只能通过我提供的API进行操作。例如。我将它们作为接口传递给它们某种外观,它们只能调用它,而不是调用任何其他程序集。我不能拥有可以随意在Web服务器上执行操作的插件,例如影响文件系统。
  • 插件中的致命崩溃不会影响核心应用程序的稳定性。

似乎System.AddIn是我最好的选择,但我不清楚如何强制加载的插件只能通过我提供的API工作,而不是加载任何其他程序集。 System.AddIn是否提供该功能?另外,System.AddIn可以与ASP.NET / IIS一起使用吗?

除了System.Addin,我还有哪些其他选项?

3 个答案:

答案 0 :(得分:5)

您的主要关注点似乎是隔离(为了安全性和稳健性)。

因此,您最好的选择是在单独的AppDomain中激活您的插件。在此域中,您可以控制允许加载的程序集(请参阅AppDomainSetup类)。

您的主代码也将受到保护,免受插件内发生的任何不良事件的影响:所有插件方法都必须使用核心对象的副本(除非您传递的对象继承自MarshalByRefObject,在这种情况下,所有赌注都是关闭)。 addin方法中的例外可以通过将所有调用包装在try除外,或通过AppDomain的UnhandledExcption事件来处理。

请记住,跨越AppDomain边界会有性能损失。这个电话基本上是一个远程呼叫。

另一个潜在的问题是您打算如何管理AppDomains。我从未试图在一个过程中创建多个AppDomain,但我希望在这里遇到麻烦。在单个域中为多个用户组合Addins将挑战您尝试构建的保护

回应@RationalGeek问题 - UnhandledException event允许这样做 - 有点儿。您可以在核心域和插件域中订阅此事件,但这样做有很多不确定性 - 请参阅我引用的文章以获取更多详细信息。可能更好的选择是在try / except

中包装对API的每次调用

答案 1 :(得分:1)

您可以尝试使用AppDomains并处理未处理的异常。为避免appdomain崩溃,您必须处理AppDomain.UnhandledException

在上面的链接中,请注意以下声明

从.NET Framework 4开始,不会针对损坏进程状态的异常(例如堆栈溢出或访问冲突)引发此事件,除非事件处理程序是安全关键的并且具有HandleProcessCorruptedStateExceptionsAttribute属性

因此您可能需要明确处理某些配置。

我已经阅读了很多问题,声称当未处理的异常发生在子域中的不同线程上时,会冒泡并关闭父域。如果是这样,那么将所有插件加载到一个单独的进程中,每个插件都有一个appdomain或者将插件加载到单独的进程中可能是可取的。

我也发现了以下问题,我相信你会发现非常有帮助的

答案 2 :(得分:-1)

为什么不在运行时使用反射并发现可用的插件? Assembly.LoadFile来获取程序集, GetExportedTypes来获取您的对象 使用Activator.CreateInstance

创建实例

然后在try循环中运行插件以确保它不会影响系统。虽然您需要一些重要的架构来提供实际稳定性。

除非您有复杂的插件管理方案,否则请远离MEF。如果它只是允许用户使用他们自己的一些,只需使用反射。