在新的 Appdomain 中加载程序集,需要完全信任父程序集

Posted

技术标签:

【中文标题】在新的 Appdomain 中加载程序集,需要完全信任父程序集【英文标题】:Load Assembly in new Appdomain, needs parent assembly to be fully trusted 【发布时间】:2018-03-05 16:47:02 【问题描述】:

我在我的主应用程序中运行一个宏程序集。宏不需要访问父程序集。这是sn-p:

Assembly ParentAssembly

    class c1
     
        void RunMacro()  
        
            System.Security.PermissionSet PS = new System.Security.PermissionSet(PermissionState.None);
            PS.AddPermission(new SOME_PERMISSIONS....);
            AppDomainSetup ADS = new AppDomainSetup();
            ADS.ApplicationBase = "c:";
            AppDomain domain = AppDomain.CreateDomain(SomeName, null, ADS, PS);

            System.Runtime.Remoting.ObjectHandle handle = Activator.CreateInstanceFrom(domain, typeof(Sandboxer2).Assembly.ManifestModule.FullyQualifiedName, typeof(Sandboxer2).FullName);
            Sandboxer2 m = (Sandboxer2)handle.Unwrap();
            m.Execute();
        
    

我收到此异常:

通过安全透明方法尝试 'SandBoxer.Sandboxer2.Execute()' 访问安全关键方法 'System.AppDomain.add_AssemblyResolve(System.ResolveEventHandler)' 失败了。

Assembly 'Parent Assembly full name...' 是部分信任的,它 导致 CLR 使其完全安全透明,无论 装配本身中的任何透明度注释。为了 访问安全关键代码,此程序集必须完全受信任。

我的问题:

    有什么办法可以避免在子程序集中加载父程序集?

    在我的代码第二行,什么权限可以解决问题?

    SandBoxer 的 AssemblyResolve 事件会在运行时加载一些程序集。程序集从数据库作为二进制数组或从 GAC 加载。他们并不完全信任。我通过在第二行代码中添加的权限对象来控制他们的行为。是否必须添加特殊权限才能让它们仅作为部分受信任的程序集加载?

我认为一切都可以通过添加第二行代码之类的安全权限来完成,如果我对这个概念有误解,我将不胜感激。

EDIT1: 父程序集是创建 SandBoxr 实例并运行它的主应用程序的程序集。请看一下 SandBoxer2 类及其 Execute 方法:

public class Sandboxer2 : MarshalByRefObject

    public void Execute()
    
        AppDomain ad = AppDomain.CurrentDomain;
        ad.AssemblyResolve += MyHandler;
        .
        .
        .
    

在 Execute 方法内部,实例化 ad 后,我使用了 ad.GetAssemblies(),这是所有已加载程序集的列表。第 2 行从沙盒程序执行的最开始就包含 ParentAssembly。

[0] mscorlib,版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089 System.Reflection.Assembly System.Reflection.RuntimeAssembly [1] System.Web,版本=4.0.0.0,文化=中性,PublicKeyToken=b03f5f7f11d50a3a System.Reflection.Assembly System.Reflection.RuntimeAssembly [2] ParentAssembly,版本=1.0.0.0,Culture=neutral,PublicKeyToken=null System.Reflection.Assembly System.Reflection.RuntimeAssembly [3] System.Data,版本=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089 System.Reflection.Assembly System.Reflection.RuntimeAssembly [4] 系统,版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089 System.Reflection.Assembly System.Reflection.RuntimeAssembly [5] MacroBase_IO,版本=1.0.0.0,文化=中性,PublicKeyToken=null System.Reflection.Assembly System.Reflection.RuntimeAssembly [6] System.Core,版本=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089 System.Reflection.Assembly System.Reflection.RuntimeAssembly [7] System.Configuration,版本=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a System.Reflection.Assembly System.Reflection.RuntimeAssembly [8] System.Xml,版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089 System.Reflection.Assembly System.Reflection.RuntimeAssembly

【问题讨论】:

你称之为“父”的程序集是什么? (显然没有一个持有SandBoxer2,但没有提到其他程序集)。使用特定名称可能会更好(即使与您在实际代码中使用的名称不完全匹配)。 我已经编辑了我的问题。 ParentAssembly 是我的第一个 sn-p。 【参考方案1】:

回答问题 1 和 2:

Sandboxer 必须位于单独的程序集(另一个 DLL)中,并且该单独的程序集必须使用密钥进行签名。然后,主应用程序将不会自动加载,也不会引发此异常。

编辑:

1- 使用密钥签名是通过“Assembly-Signing”选项卡的 Properties 完成的。

2- 这个sample 有助于理解如何将程序集定义为完全信任并将强名称引入沙盒。

【讨论】:

以上是关于在新的 Appdomain 中加载程序集,需要完全信任父程序集的主要内容,如果未能解决你的问题,请参考以下文章

ApplicationManager.CreateObject 无法在新的 AppDomain 中加载程序集

在 AppDomain 问题中加载具有依赖项的程序集

在不同的 AppDomain 中加载具有依赖项的程序集

在新的 AppDomain 中加载插件

在新的 appdomain 中加载 C 模块失败

在新的应用程序域中加载程序集