我正在尝试创建一个沙盒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
为真,并且该方法同时将IsSecurityCritical
和IsSecuritySafeCritical
设置为true,IsSecurityTransparent
为false。
我将整个项目压缩到http://davidhogue.com/files/PluginLoader.zip以防止这种情况变得更容易。
如果有人有任何想法,我将非常感激。我似乎陷入了死胡同。
答案 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);
}