在自定义 AppDomain 中附加内存程序集
Attach in-memory assembly in custom AppDomain
我已经创建了一个沙盒AppDomain
:
public AppDomain CreateSandbox()
{
var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase };
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.NoFlags));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissionSet.AddPermission(new FileIOPermission(PermissionState.Unrestricted)); // TODO: Restrict IO
var appDomain = AppDomain.CreateDomain("Sandbox", null, setup, permissionSet);
return appDomain;
}
我还有一个从 byte[] fileData
:
加载的程序集
var assembly = Assembly.Load(fileData);
var appDomain = CreateSandBox();
如何将此程序集或 fileData
字节加载到 appDomain
中然后使用它?
您可以使用新的 AppDomain 来完成它。您必须实例化一个 class(继承 MarshalByRefObject
),它将 运行 在所选的 AppDomain 中并为您加载程序集。这涉及 .NET 远程处理。 Tell me more in this MSDN article。尽管它提到了部分受信任的代码,但大部分内容仍然适用。
在沙箱域中让 class 继承 MarshalByRefObject
运行ning 加载程序集非常重要,以防代码不是 trust-worthy。
Proxy/Sandbox/Helper Class
此 class 充当您在主 AppDomain(您创建 child 域的地方)中的代码 运行 与您希望 运行 在 sandbox/child 域中。使用 child 域时,出于安全原因,主域中的 objects 只能直接与 child 域中 运行ning 的代理 class 对话。
通信是在幕后通过 .NET Remoting 进行的 - 您可能不知道。因此,为什么 class 是 MarshalByRefObject
.
例如(修改后的 MSDN 示例)
class Sandboxer:MarshalByRefObject
{
public void LoadDodgyAssembly(string path) { ... }
}
主机代码
在创建 child AppDomain 的地方使用此代码。以下代码应 运行 在主 AppDomain 中:
var appDomain = CreateSandBox();
var handle = Activator.CreateInstanceFrom(
appDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
typeof(Sandboxer).FullName );
var sandboxer = (Sandboxer) handle.Unwrap();
sandboxer.LoadDodgyAssembly("pleaserunme.dll");
Return 值
注意你的代理 class returns 到你在主 AppDomain 中的调用代码。如果您不信任加载的程序集,最好将您的方法标记为 void
,否则请考虑使用您自己的可信任类型标记为 [Serializable]。
告诉我更多
大约在 2005 年左右,MSDN 杂志中有一篇精彩的文章,标题为 "Add-ins: 你相信它吗" 或类似但找不到的文章。
我已经创建了一个沙盒AppDomain
:
public AppDomain CreateSandbox()
{
var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase };
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.NoFlags));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissionSet.AddPermission(new FileIOPermission(PermissionState.Unrestricted)); // TODO: Restrict IO
var appDomain = AppDomain.CreateDomain("Sandbox", null, setup, permissionSet);
return appDomain;
}
我还有一个从 byte[] fileData
:
var assembly = Assembly.Load(fileData);
var appDomain = CreateSandBox();
如何将此程序集或 fileData
字节加载到 appDomain
中然后使用它?
您可以使用新的 AppDomain 来完成它。您必须实例化一个 class(继承 MarshalByRefObject
),它将 运行 在所选的 AppDomain 中并为您加载程序集。这涉及 .NET 远程处理。 Tell me more in this MSDN article。尽管它提到了部分受信任的代码,但大部分内容仍然适用。
在沙箱域中让 class 继承 MarshalByRefObject
运行ning 加载程序集非常重要,以防代码不是 trust-worthy。
Proxy/Sandbox/Helper Class
此 class 充当您在主 AppDomain(您创建 child 域的地方)中的代码 运行 与您希望 运行 在 sandbox/child 域中。使用 child 域时,出于安全原因,主域中的 objects 只能直接与 child 域中 运行ning 的代理 class 对话。
通信是在幕后通过 .NET Remoting 进行的 - 您可能不知道。因此,为什么 class 是 MarshalByRefObject
.
例如(修改后的 MSDN 示例)
class Sandboxer:MarshalByRefObject
{
public void LoadDodgyAssembly(string path) { ... }
}
主机代码
在创建 child AppDomain 的地方使用此代码。以下代码应 运行 在主 AppDomain 中:
var appDomain = CreateSandBox();
var handle = Activator.CreateInstanceFrom(
appDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
typeof(Sandboxer).FullName );
var sandboxer = (Sandboxer) handle.Unwrap();
sandboxer.LoadDodgyAssembly("pleaserunme.dll");
Return 值
注意你的代理 class returns 到你在主 AppDomain 中的调用代码。如果您不信任加载的程序集,最好将您的方法标记为 void
,否则请考虑使用您自己的可信任类型标记为 [Serializable]。
告诉我更多
大约在 2005 年左右,MSDN 杂志中有一篇精彩的文章,标题为 "Add-ins: 你相信它吗" 或类似但找不到的文章。