【发布时间】:2016-10-27 12:47:09
【问题描述】:
我正在使用单独的AppDomain 作为沙箱,并尝试执行通过反射构造的方法。
当方法被调用时,一个
安全异常
...被抛出,即使沙盒 AppDomain 在其 PermissionSet 上设置了 ReflectionPermission(PermissionState.Unrestricted)。
当PermissionSet 设置为PermissionState.Unrestricted 时调用确实有效,但这违背了沙盒的目的。
这是一个演示该问题的示例:
using System;
using System.Security;
using System.Security.Permissions;
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
var person = new Person();
var program = new Program();
var customDomain = program.CreateDomain();
var result = program.Execute(customDomain, (x) =>
{
var type = x.GetType();
var propertyInfo = type.GetProperty("Name");
var method = propertyInfo.GetMethod;
var res = method.Invoke(x, null) as string;
return res;
}, person);
Console.WriteLine(result);
Console.ReadLine();
}
public object Execute(AppDomain domain, Func<object, object> toExecute, params object[] parameters)
{
var proxy = new Proxy(toExecute, parameters);
var result = proxy.Invoke(domain);
return result;
}
private AppDomain CreateDomain()
{
var appDomainSetup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
ApplicationName = "UntrustedAppDomain"
};
// Set up permissions
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new SecurityPermission(PermissionState.Unrestricted));
permissionSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
// Create the app domain.
return AppDomain.CreateDomain("UntrustedAppDomain", null, appDomainSetup, permissionSet);
}
private sealed class Proxy : MarshalByRefObject
{
private Delegate method;
private object[] args;
private object result;
public Proxy(Delegate method, params object[] parameters)
{
this.method = method;
this.args = parameters;
}
public object Invoke(AppDomain customDomain)
{
customDomain.DoCallBack(Execute);
return this.result;
}
private void Execute()
{
this.result = this.method.DynamicInvoke(this.args);
}
}
}
public class Person
{
public Person()
{
this.Name = "Test Person";
}
public string Name { get; set; }
}
}
【问题讨论】:
-
您正试图从辅助域的上下文中对 primary
AppDomain中创建的对象执行方法。换句话说,沙箱中的代码试图调用不允许的主域中的代码。通过AppDomains 使用沙盒时,必须在沙盒域中通过主应用程序域的CreateInstanceAndUnwrap创建Proxy。 -
@MickyD 感谢您的回复。如果在沙箱域中创建
Proxy,并且Person类是Serializable,则上面的示例代码可以工作,但是在二级域中使用的人对象确实与主域 - 它在CreateInstanceAndUnwrap方法中被序列化。 -
Person必须首先设为Serializable。如果您不想传递副本,请使用MarshalByRefObject。请参阅下面的答案
标签: c# reflection appdomain