具有SecuritySafeCritical功能的C#完全受信任的程序集仍然会引发安全异常

时间:2010-09-13 22:47:21

标签: c# appdomain securityexception

我正在尝试创建一个沙盒AppDomain来加载扩展/插件。我有一个MarshalByRefObject,它在appdomain中实例化以加载dll。我在尝试加载dll时遇到SecurityExceptions,我无法弄清楚如何绕过它们,同时仍然限制第三方代码可以做什么。我的所有项目都是.net 4。

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

这是我的Loader类,它创建AppDomain并跳转到它:

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以防止这种情况变得更容易。

如果有人有任何想法,我将非常感激。我似乎陷入了死胡同。

1 个答案:

答案 0 :(得分:6)

一开始你可能不应该将该功能标记为SecuritySafeCritical,因为这意味着不受信任的呼叫者可以打电话给你,你可能并不真正想要(不是它应该是一个主要问题)。

至于你的问题,问题是默认你仍然没有使用任何特殊权限运行,正常的简单方法来进行程序集加载是你创建自己的AppDomainSetup并将它的ApplicationBase指向某种类型的Plugin目录(一般来说这不是一个坏主意),然后你可以使用普通的Assembly.Load(“AssemblyName”)加载出基数。但是,如果必须加载任意文件,则需要为插件dll(完整路径)声明FileIOPermission,即

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

    return Assembly.LoadFile(file);
}