ASP.NET:如何通过程序集在每个页面上设置不同的信任级别?

8
我有两个Web应用程序(预编译站点),一个是第一方应用,将以完全信任的方式运行。另一个是第三方应用,应该在部分信任(或特定权限)下运行。 TrustedAssembly.Web.Pages.MyPage 应该在完全信任的默认应用程序域中运行。 UntrustedAssembly.Web.Pages.SomePage 应该在部分信任的应用程序域中运行。
此外,如果 TrustedAssembly.Web.Pages.MyPage 动态加载 UntrustedAssembly.Web.Controls.SomeControl,是否可以使控件在部分信任和/或特定权限下运行,而页面在完全信任下运行?
反之亦然,例如,UntrustedAssembly.Web.Controls.SomePage 动态加载 TrustedAssembly.Web.Controls.MyControl,是否可以使控件在完全信任下运行,而页面在部分信任下运行?
更新/ FYI:这是.NET 4。
2个回答

5

这可能有点棘手。以下是两种可能的思路:

第一种是在中等信任级别下运行应用程序,但将您想要在完全信任级别下运行的任何内容放置在GAC中,并将您想要在部分信任级别下运行的内容放置在bin中。

请注意,在您的“反之亦然”情况下,受信任的控件可能需要在执行完全信任操作之前执行安全“断言”。例如:

(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();

第二种思路是以完全信任的方式运行应用程序,然后使用自定义 证据 加载任何要在中等信任级别下运行的程序集,例如:
var evidence = new Evidence();
// Initialize the Evidence
Assembly.LoadFrom(path, evidence);

但请注意,正确设置Evidence对象并非易事,我不确定我是否要走这条路。

这不是完整的回答,但希望能提供一些思路 :)


我喜欢从GAC运行第一方代码的想法,但我们需要积极拒绝SecurityPermission断言,因为授予的交互级别由最终用户在其隐私偏好中控制。因此,例如,一个控件可能已被授予x、y和z权限,而另一个控件可能只有x权限。使用证据加载程序集可能是唯一的选择。您有没有任何好的文章可以更详细地扩展这个主题 - 特别是关于从该程序集加载控件以及运行时/编译时影响方面的问题? - lukiffer
我找不到任何很好的讨论这个问题的资料。棘手的部分是程序集通常由ASP.NET加载,因此您无法自己调用LoadFrom。驱动加载的一个选项可能是将程序集放置在其他文件夹(而不是bin),然后使用AssemblyResolve事件以您想要的方式加载它们。 - David Ebbo
我可以将FileIOPermission添加到PermissionSet中,并将该权限集提供给AppDomain.CreateDomain方法,但问题是我无法附加到根AppDomain的AssemblyResolve事件以将其(程序集或类型)解析为在具有正确权限的AppDomain中运行的“远程”实例。 有什么想法吗? - lukiffer
请注意,我并不建议进行任何跨域远程操作(请参见Alexei的回复),而只是在同一域中以不同的方式加载一些程序集。您可以在域启动时(例如从Application_Start)注册AssemblyResolve。但请注意,我并不声称在这里拥有完整的端到端解决方案,因为我还没有做过这个! - David Ebbo
这让我有很多思考的地方,但我认为已经指引我走上了正确的道路。现在...需要进行大量的重新设计和重构。 :) - lukiffer

3

+1给David Ebbo - 在部分信任下运行整个应用程序并在来自GAC的程序集中调用时提升权限是唯一明智的方法。

还有一些需要考虑的要点...

  • 设计为在应用程序域之间进行远程处理的类并不多。ASP.Net的类并不非常适合远程处理...
  • ASP.Net控件与运行时有很多集成点。您需要构建非常有趣的代理类,以正确限制控件和运行时之间的交互,以避免潜在的提升并具有正确的跨域封送。
  • 很容易在域边界上“泄漏”来自其他程序集的类(通过从自定义位置进行自定义加载可以帮助防止“泄漏”,使故障更加明显)。使用具有许多扩展点(重写、事件)的框架(如ASP.Net)会增加将对象带入跨域的机会。
  • 这不能帮助您在进程中运行任意代码 - 您只需将自定义代码加载到进程中即可声明信任(非CLR意义)。也就是说,具有执行权限的代码可以实现StackOverflow,并可靠地使您的进程崩溃。

同意在应用程序域之间使用远程调用可能不是可行的方法。 - David Ebbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接