2010-09-13 229 views
4

我想创建一个沙箱AppDomain加载扩展/插件。我有一个MarshalByRefObject,它在appdomain内部实例化以加载dll。我在尝试加载dll时遇到了SecurityExceptions,我无法弄清楚如何绕过它们,同时还限制了第三方代码可以执行的操作。我的所有项目都是.net 4.C#完全信任的程序集与SecuritySafeCritical功能仍然抛出SecurityExceptions

InDomainLoader类位于完全受信任的域中,该方法标记为SecuritySafeCritical。从我读过的所有内容中,我认为这应该起作用。

下面是创建的AppDomain中并跳转到它在我的Loader类:

public class Loader 
{ 
    public void Load(string dll, string typeName) 
    { 
     Log.PrintSecurity(); 

     // Create new AppDomain 
     var setup = AppDomain.CurrentDomain.SetupInformation; 
     var permissions = new PermissionSet(null); 
     permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 
     var strongname = typeof(InDomainLoader).Assembly.Evidence.GetHostEvidence<StrongName>(); 
     var strongname2 = typeof(IPlugin).Assembly.Evidence.GetHostEvidence<StrongName>(); 
     AppDomain domain = AppDomain.CreateDomain("plugin", null, setup, permissions, strongname, strongname2); 

     // Create instance 
     var loader = (InDomainLoader)domain.CreateInstanceAndUnwrap(
      typeof (InDomainLoader).Assembly.FullName, typeof (InDomainLoader).FullName); 

     // Jump into domain 
     loader.Load(dll, typeName); 
    } 
} 

而这里的是,在域中运行的引导加载程序:

public class InDomainLoader : MarshalByRefObject 
{ 
    [SecuritySafeCritical] 
    public void Load(string dll, string typeName) 
    { 
     Log.PrintSecurity(); 

     var assembly = Assembly.LoadFrom(dll); // <!-- SecurityException! 
     var pluginType = assembly.GetType(typeName); 

     var demoRepository = new DemoRepository(); 
     var plugin = (IPlugin)Activator.CreateInstance(pluginType, demoRepository); 
     Console.WriteLine(plugin.Run()); 
    } 
} 

一些日志语句告诉我,程序集的IsFullyTrusted为真,且该方法将IsSecurityCriticalIsSecuritySafeCritical设置为true,IsSecurityTransparent为false。

我将整个项目压缩到http://davidhogue.com/files/PluginLoader.zip以防万一,这样做更容易。

如果有人有任何想法,我会非常感激。我似乎在这里陷入死胡同。

回答

6

对于一开始你可能不应该将该函数标记为SecuritySafeCritical,因为这意味着不受信任的调用者可以调用您,您可能并不真正想要它(不是它应该是一个主要问题)。

至于你的问题,问题是,默认情况下,你仍然不会运行任何特殊的权限,正常的简单的方法来做组装加载是你创建自己的AppDomainSetup,并指出它的ApplicationBase在一些插件目录kind(这通常不是一个坏主意),那么你可以使用正常的Assembly.Load(“AssemblyName”)来加载基础。然而,如果你必须加载一个任意文件,那么你需要为插件DLL(完整路径)声明FileIOPermission,即

private Assembly LoadAssemblyFromFile(string file) 
{ 
    FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, file); 
    perm.Assert(); 

    return Assembly.LoadFile(file); 
} 
+0

好吧,我会试试看。我认为这会让我解决当前的问题。虽然,我的集会不应该完全信任,因此能够做几乎任何想要的事情? – 2010-09-14 05:31:23

+1

它是完全可信的,就在你得到安全异常的时候_thread_(对于任何更好的定义)不是。完全信任允许您声明正确的权限,如果该函数在部分信任程序集中,那么它将不被允许,除非它明确位于授权集中。 – tyranid 2010-09-14 05:45:33

相关问题