在尝试创建具有以下限制权限的System.Security.SecurityException The demand was for: <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true"/>时,我将获得AppDomain:
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, System.Reflection.Assembly.GetExecutingAssembly().Location));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));这条错误消息告诉我,它将接受至少一个不受限制/完全信任的环境,但我不明白为什么需要这样做,也不知道如何修复它。
我只将Stub的一个实例创建到新的受限AppDomain中:
public interface IHostStub // Implemented by a MarshalByRefObject object in the primary AppDomain
{
void Ping();
void SayTime(DateTimeOffset time);
}
// In the restricted AppDomain
class Stub : MarshalByRefObject
{
public event EventHandler OnQuit;
public void RequestTime(IHostStub host)
{
host.SayTime(DateTimeOffset.Now);
}
public void Quit(IHostStub host)
{
if (this.OnQuit != null)
this.OnQuit(this, new EventArgs());
}
}请你向我解释一下这条错误信息好吗?也许我误解了Unrestricted的意思。但是,将其设置为Unrestricted似乎使应用程序域自由支配(正如我预期的那样),而不考虑我添加或不添加到它的任何权限。
谢谢!
====
作为对@Nicole的回应,并在我完成这个过程中添加了一些发现,下面有两个代码示例。这是一个棘手的场景--沙箱插件--这需要太多的代码来显示所有的内容。第一个代码示例演示了异常。它有一个明显的修复,但它没有考虑到整个场景。
class Program
{
static void Main(string[] args)
{
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, currentAssembly.Location));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));
permissionSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
var appDomain = AppDomain.CreateDomain(
"Sandboxed",
null,
new AppDomainSetup
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase
},
permissionSet,
Assembly.GetExecutingAssembly().Evidence.GetHostEvidence<StrongName>());
try
{
var stub = (Stub)appDomain.CreateInstanceFromAndUnwrap(
currentAssembly.Location,
typeof(Stub).FullName);
}
catch (SecurityException ex)
{
Console.WriteLine(ex);
throw;
}
}
}
// In the restricted AppDomain
class Stub : MarshalByRefObject
{
}在该示例中,ApplicationBase与主AppDomain相同。此外,程序集本身被列为AppDomain的AppDomain程序集。最简单的解决办法是删除这个完全信任的参数。
在下一个示例中,为了防止插件加载主机程序集,ApplicationBase被设置为一个甚至不需要存在的随机路径( PermissionState.Unrestricted可以很好地工作,如果目录确实存在的话,同样的错误)。AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;需要完全信任AFAIK,所以我必须列出具有完全信任的程序集(我认为它应该覆盖为该受信任程序集设置的对AppDomain的任何限制,而不是它可能加载的其他程序集)--这个程序集可以只是“加载器”,并且插件将是另一个程序集的一部分,对该程序集应该强制执行受限制的权限。我必须自定义AssemblyResolve,因为目录不存在(或者是空的),而且我想要控制加载其他程序集(例如,从byte[])。
class Program
{
static void Main(string[] args)
{
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, currentAssembly.Location));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));
permissionSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
string path;
do
{
path = Path.GetTempPath() + Path.GetFileNameWithoutExtension(Path.GetRandomFileName());
} while (Directory.Exists(path));
var appDomain = AppDomain.CreateDomain(
"Sandboxed",
null,
new AppDomainSetup
{
ApplicationBase = path
},
permissionSet,
Assembly.GetExecutingAssembly().Evidence.GetHostEvidence<StrongName>());
try
{
var stub = (Stub)appDomain.CreateInstanceFromAndUnwrap(
currentAssembly.Location,
typeof(Stub).FullName);
}
catch (SecurityException ex)
{
Console.WriteLine(ex);
throw;
}
}
}
class Stub : MarshalByRefObject
{
static Stub()
{
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
}
public static Assembly AssemblyResolve(object sender, ResolveEventArgs e)
{
if (e.Name == Assembly.GetExecutingAssembly().FullName)
return Assembly.GetExecutingAssembly();
else
Console.WriteLine("Unable to load {0}", e.Name);
return null;
}
}发布于 2014-01-07 18:19:29
尝试通过Activator.CreateInstanceFrom而不是AppDomain.CreateInstanceFromAndUnwrap创建存根句柄。权限验证不同,使用Activator方法还可以避免向沙箱应用程序域添加额外的权限(除了SecurityPermission\Execution)。例如:
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
var appDomain = AppDomain.CreateDomain(
"Sandboxed",
null,
new AppDomainSetup { ApplicationBase = CreateFakePath() },
permissionSet,
currentAssembly.Evidence.GetHostEvidence<StrongName>());
var stub = (Stub)Activator.CreateInstanceFrom(appDomain, currentAssembly.Location, typeof(Stub).FullName).Unwrap();
var hostStub = new HostStub();
stub.RequestTime(hostStub);https://stackoverflow.com/questions/20957089
复制相似问题