c# - .net 4.0 安全模型。另一个 "Inheritance security rules violated by type..."异常

标签 c# .net appdomain code-access-security typeloadexception

我认为我坚持使用 .net 4.0 新安全模型。通常,我只想将 3rd 方程序集加载到沙箱中。听起来很简单,对吧?尽管如此……

我的解决方案中有 2 个项目:CrossAppDomain.exe 和 UntrustedCode.dll。 在 CrossAppdomain 中,我为所有可编码创建了以下基类:

public abstract class Marshallable : MarshalByRefObject, IDisposable
{
    [SecurityCritical]
    public override object InitializeLifetimeService()
    {
        return null;
    }

    public void Dispose()
    {
        if (!RemotingServices.IsTransparentProxy(this))
        {
            RemotingServices.Disconnect(this);
        }
    }
}

并为我将使用的对象创建了基类

public abstract class BaseClass : Marshallable
{
}

在 UntrustedCode.dll 中我创建了派生类

public class UntrustedClass : BaseClass
{
}

要创建 UntrustedClass 的实例,我使用以下工厂:

   public sealed class Factory
{
    public BaseClass Create(string assName, string typeName)
    {
        var domain = CreateAppDomain();

        ObjectHandle handle;
        try
        {
            // This throws SecurityException with informational message "RequestFailed"
            handle = domain.CreateInstance(typeof(AppDomainWorker).Assembly.FullName, typeof(AppDomainWorker).FullName);
        }
        catch (SecurityException)
        {
            // While this works fine...
            handle = Activator.CreateInstanceFrom(domain,
                                                      typeof(AppDomainWorker).Assembly.ManifestModule.FullyQualifiedName,
                                                      typeof(AppDomainWorker).FullName);
        }
        var worker = (AppDomainWorker)handle.Unwrap();
        worker.LoadAssemblies();

        var obj = worker.Create(assName, typeName);
        worker.Dispose();
        return obj;
    }

    private AppDomain CreateAppDomain()
    {
        var name = Guid.NewGuid().ToString();
        var permissions = new PermissionSet(PermissionState.None);
        permissions.AddPermission(new SecurityPermission(PermissionState.Unrestricted));
        permissions.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
        permissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
        var appSetup = new AppDomainSetup
            {
                ApplicationName = name,
                ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
                ShadowCopyDirectories = Path.GetFullPath(@"..\..\..\UntrustedCode\bin"),
                ShadowCopyFiles = "true"
            };
        // Since Marshallable.InitializeLifetimeServices is overriden and marked with [SecurityCritical] 
        // we should add this assembly in full trusted list.
        // Otherwise. TypeLoadException is thrown with message "Inheritance security rules violated while overriding member: 
        // 'CrossAppDomains.Marshallable.InitializeLifetimeService()'. Security accessibility of the overriding method must 
        // match the security accessibility of the method being overriden.
        var sn = typeof (AppDomainWorker).Assembly.Evidence.GetHostEvidence<StrongName>();
        var domain = AppDomain.CreateDomain(name, null, appSetup, permissions, sn);
        return domain;
    }

    private sealed class AppDomainWorker : Marshallable
    {
        public BaseClass Create(string assName, string typeName)
        {
            var assembly = AppDomain.CurrentDomain.GetAssemblies()
                                    .Single(a => assName.StartsWith(a.GetName().Name));

            // Here TypeLoadException is thrown: Inheritance security rules violated by type: 'UntrustedCode.UntrustedClass'. 
            // Derived types must either match the security accessibility of the base type or be less accessible.
            var obj = (BaseClass)Activator.CreateInstanceFrom(assembly.Location, typeName).Unwrap();
            Debug.Assert(!RemotingServices.IsTransparentProxy(obj));
            return obj;
        }

        public void LoadAssemblies()
        {
            var assemblyName = AssemblyName.GetAssemblyName(Path.GetFullPath(@"..\..\..\UntrustedCode\bin\Debug\UntrustedCode.dll"));
            Assembly.Load(assemblyName);
        }
    }
}

问题来了:

  1. 在 Factory.Create() 中,我仅在使用 Activator.CreateInstance 时才成功创建 AppDomainWorker 类。而更直接的 AppDomain.CreateInstanceAndUnwrap 失败了。这看起来很不稳定,我的意思是这是错误或安全漏洞。但是没关系,解决方法有效

  2. 在 AppDomainWorker.Create() 中我得到 TypeLoadException:类型违反了继承安全规则:'UntrustedCode.UntrustedClass'。派生类型必须与基类型的安全可访问性相匹配或更难访问。我不知道如何解决它。这是我的问题

    附言我知道 [assembly: SecurityRules(SecurityRuleSet.Level1)] ,但我想知道如何让事情在 .net 4.0 安全模型中工作

编辑: 添加 [assembly: AllowPartialTrustCallers] 后,我遇到了一大堆新问题:我需要用 [SecuritySafeCritical] 明确标记所有使用 LogManager.GetCurrentClassLogger() 创建 nlog loggger 的代码,然后是所有使用带有记录器的初始化字段的代码。这是 Not Acceptable 。那么也许还有其他解决方法?

最佳答案

我认为,我只需将 UntrustedClass 使用的类和使用安全关键代码的代码移动到单独的程序集中。

即将 BaseClass、Marshallable、Factory 移动到某些 Api.dll 中。然后用 [APTCA] 标记程序集并用 [SecuritySafe] 修饰必要的方法。那么任何现有代码都应该可以正常工作,因为 [APTCA] 仅适用于 Api.dll。

此方法适用于示例项目,但我不能确定它是否适合我当前的项目。我会在实现后立即通知您。

关于c# - .net 4.0 安全模型。另一个 "Inheritance security rules violated by type..."异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21550175/

相关文章:

java - 对应于 C# 中的匿名接口(interface)实现

c# - 有谁知道如何在 ParallelExtensionExtras 中使用 IOCompletionPortTaskScheduler 和 IOTaskScheduler 以及它们的用途是什么?

c# - 在任何情况下,异步等待方法内的对象更改在完成后是否可见?

c# - 我的 winform 应用程序关闭时如何停止线程

appdomain - 程序集无法在影子复制的 AppDomain 中加载

c# - Property Lambda 表达式获得额外的 Convert(p=>p.Property)

c# - TDD:测试构造函数设置属性是否有意义?

c# - "x is null"和 "x == null"有什么区别?

c# - 为什么我的 C# AppDomain 前一秒还好,下一秒就抛出异常?

ASP.NET 全局/静态存储?