我有一个程序和一个简单的插件架构,其中插件实现了通用接口,主程序加载了实现此接口的所有插件。这是迄今为止我发现的最常见的自定义插件架构,所以我正在使用它。
我没有使用微软的MEF,我有理由不这样做。我会留下它。
问题在于,当加载插件时,无论它们对主程序有多么“盲目”,而且它是表单/类/等。它仍然可以访问System.Windows.Forms.Application
,因此可以访问我的应用程序及其当前运行的表单/方法/控件/等。
我不想要这个。有没有办法限制插件对主应用程序的访问?
编辑:有关插件的更多信息
我们(我的老板和我)目前正在讨论插件需要做什么。他们显然都需要添加功能,但我们最初决定让每个插件访问当前运行的表单,以便它可以直接向表单添加控件和事件。这是基于这样的假设:只有我们开发人员才会编写它们。
现在我们正在考虑第三方插件的可能性,显然,原始设计与开放式门上的“请勿进入”标志具有相同的安全性,而周围没有人。
或者在万圣节那天挂在一碗个人吃喝玩乐上的“Take One”标志。
答案 0 :(得分:4)
如果您可以在自己的AppDomains
中运行插件,那肯定会增加隔离级别。尽管如此,它也可能使与他们沟通变得很痛苦。如果不了解插件的意图,很难知道这是否合适。
答案 1 :(得分:4)
这样做的一种方法是将您的插件托管在自己的AppDomain中。您可以将这些AppDomain配置为具有有限的安全性,以防止它们访问主AppDomain中的资源。这确实使事情变得复杂,但会给你带来的沙子拳击。
您从AppDomain托管中获得的另一个好处是,如果您希望刷新插件,可以加载和卸载这些域,此外,您还可以保护主AppDomain免受“子”域中的崩溃。
<强>更新强>
看到您的更新后重新开始。如果您的插件必须能够直接访问UI元素,那么您的插件的功能将无法提供帮助,例如:访问表单以添加控件。您将无法通过AppDomain边界直接访问表单,也无法在一个AppDomain中生成控件,然后将它们编组到另一个AppDomain中。
您仍然可以考虑在另一个AppDomain中托管插件,但是您需要考虑某种代理机制,以便可以代表插件为表单添加控件等操作,而不是让插件访问形式直接。例如,您可以传入一个表单构建器对象,该对象具有AddButton
等方法。然后,代理可以代表主域中的插件执行这些操作。通过这种方式,您可以为插件提供有限的API以及所需的事件。
这种方法绝不是微不足道的,但是一旦掌握了基础知识,它就不会太复杂。
更新2
自从当天推出自己的AppDomins插件框架以来,事情已经发生了变化。现在支持从.Net框架到3.5以后插件:
MAF - Managed Addin Framework / System.Addin
它支持插件的AppDomain隔离模式,并具有插件加载器等。无需自己动手。
答案 2 :(得分:1)
所以重申你的主要关注点:
...因此可以访问我的应用程序及其当前运行的表单/方法/控件/等。
在着手加载,隔离和限制这些扩展的复杂而困难的方法之前,您应该了解一些关于Windows和CLR的内容。首先,该框上运行的任何程序都可以使用许多Windows API将代码注入您的进程。一旦代码被您或您的操作系统加载到您的流程中,访问CLR运行时并加载程序集和/或在现有AppDomain中运行代码相当容易。
了解这一点,你应该权衡和平衡你摘录限制'扩展'的努力。如果我构建这样的东西,我会更关心其他事情,而不是操纵我的应用程序状态的恶意扩展代码。例如,这些是您可能会考虑的事情:
除此之外,你真的没有别的事可做。正如我所说的,即使使用上述安全防护装置,任何人都可以攻击您的应用程序。您主要关心的是不要让用户感到惊讶。因此,建议您在应用程序运行的代码中进行应有的注意,但是一旦您的用户授予其访问权限,这些扩展所做的事情并不是您可以完全控制的。
这并不是说AppDomain隔离不会为您提供价值,它可能会;然而,恕我直言会在不限制其运作能力的情况下获得足够的安全限制将证明是困难的。
<强>更新强>
...但如果您将插件加载到配置了有限权限的AppDomain中,它如何使用此向量?
正如我在结束语中所说,你可以限制他们访问AppDomain中的非托管代码。这也限制了他们开发可用Windows体验的能力。我希望大多数WinForms应用程序至少使用一个PInvoke调用或非托管COM控件。这种限制可能是可以接受的,如果没有关于他们试图提供什么功能的更多信息,我真的不能说。
我试图说的是,通过安装和批准扩展程序,您的用户正在接受允许该扩展程序运行的责任。当然,假设您加载了正确的代码,那么扩展程序的作用以及它可能尝试的恶意程度不是您的责任。这就是为什么我建议您专注于运行已批准的代码,而不是担心代码在您的过程中可能会执行的操作。
答案 3 :(得分:0)
处理此问题的最佳方法是公开一个文档化的插件API。如果您的插件以完全信任的方式运行,那么即使您在其自己的AppDomain中运行插件,它也可以将自身注入到应用程序中 - 然后只需要有人使包装器可用并且所有插件都恢复到相同的状态开始。如果您的API允许插件以简单,一致和文档化的方式提供所需的功能,那么这就是插件开发人员将使用的。
以下是WPF,Windows窗体和经典Spy ++的外部UI挂钩(全部带有源代码)。