System.Addin - 创建安全的ASP.NET MVC插件

Chr*_*ris 25 asp.net asp.net-mvc plugins appdomain

最近我的重点是创建一个可以托管第三方MVC插件的ASP.NET MVC应用程序.理想情况下,这些插件的开发将遵循以下规则:

  1. 插件可以在标准MVC项目中开发,并且能够使用ASP.NET MVC框架的所有现有基础结构.
  2. 编译插件MVC项目并包含到主机MVC应用程序中的复杂性不应该很严重.
  3. 对MVC应用程序的正常开发流程的任何更改都将是最小值

经过一番研究后,我想出了以下几种方法来实现这一点,每种方法各有优缺点.

方法1 - 将MVC插件程序集加载到主MVC AppDomain中

工作流程

  • 在单独的MVC项目中开发插件.
  • 编译组件和它和任何依赖关系加载到经由所述主机应用程序PreApplicationStartMethodAttribute,MEF或主机项目中的基本组件参考(如果可能).
  • 将路由映射到插件控制器,以便将插件视为Area主机内的插件.
  • 将插件视图放入正确的区域文件夹中.需要更改布局文件,以便布局路径指向基于区域的位置,而不是应用程序的根(在开发MVC项目中就是这种情况)
  • 当插件的请求进入时,ASP.NET将使用现有区域功能将请求路由到正确的控制器并查看视图文件的正确位置.

好处

  1. 将无缝地工作,就好像控制器嵌入在主机MVC应用程序组件中一样.
  2. 在应用程序启动(PreApplicationStartMethodAttribute,项目引用)之前和应用程序启动之后(MEF),将程序集包含到主机App Domain中很简单

缺点

  1. 没有沙盒 - 控制器将具有与主机相同的信任级别.

结论

这是最简单的方法,但它也是最不安全的方法.它基本上消除了允许不受信任的开发人员创建插件的可能性,因为这些插件将具有与宿主应用程序相同的信任级别(这意味着如果宿主应用程序可以执行诸如System.IO.File.Delete插件之类的方法)

方法2 - 通过MAF在自己的AppDomain中运行的MVC插件程序集

这种方法旨在允许创建可以沙箱化为自己的MVC插件,AppDomains并由主机通过System.Addin库使用.

结构体

  1. 在主机中设置路由,以确定正在处理的URL是否针对插件.可能有这样的模式example.com/p/{plugin}/{controller}/{action}/{id}

  2. 具有上述模式的所有路由都映射到具有模块路由操作的主机控制器.该操作会查看任何给定的路由,并根据段确定处理请求的相应插件{plugin}.

  3. 插件视图是一个接收器/发送器对象,充当插件控制器的网关.它有一个名为AcceptRequest的方法,它RequestContext从主机接收a ,并返回一个ActionResult.

  4. 插件管道包含可以串行化RequestContextActionResult跨管道隔离边界传输的适配器.

执行流程

  1. 匹配插件的路由并调用插件路由控制器.

  2. 控制器将所需的插件加载到它自己的插件中AppDomain并调用AcceptRequest,通过RequestContext(通过管道序列化)

  3. AcceptRequest接收上下文并根据该请求确定要执行的适当控制器(使用自定义控制器工厂).

  4. 一旦控制器完成执行请求,它就会ActionResult向接收器对象返回一个接收器对象,然后将该接收器对象ActionResult(也通过管道序列化)传递回主机AppDomain.

  5. 最初调用AcceptRequest的控制器然后可以返回ActionResult到主机MVC执行管道,就像它自己处理请求一样.AppDomain如果愿意,可以卸载插件.

好处

插件将被沙箱化AppDomain,因此可以使用任何适合主机的权限集.

缺点

  • 必须能够序列化RequestContextActionResult.
  • 可能会破坏隔离中的其他ASP.NET MVC功能AppDomain.

结论

这种方法在纸面上听起来不错,但我不确定序列化RequestContextActionResult对象是否可行/可行,以及单独运行MVC控制器.

问题

如果代码是由可信赖的开发人员创建的,那么第一种方法就很好.我知道我不会删除所有主机视图文件或它的web.config文件.但最终,如果您希望第三方开发人员为您的MVC应用程序创建插件,您需要能够对其代码进行沙箱处理.

从我的所有研究中,System.Addin当您使用基于API的简单类库时,该库可以轻松实现主机/插件环境.但是,当涉及到MVC时,似乎并不容易做到这一点.

我有一些问题是:

  1. 我在这里概述的第二种方法是否可行?
  2. 有一个更好的方法吗?
  3. 将来是否会有更简单的方法来实现MVC插件隔离?

Pan*_*nis 0

恕我直言,System.AddIn 对于您想要做的事情来说有点矫枉过正。

您熟悉System.Security.Permissions命名空间吗?如果没有,您可以查看FileIOPermission。也许您可以通过使用(为什么不,甚至扩展).NET 的代码访问安全机制来沙箱您的可扩展系统。