我发现了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是一样的主应用程序域。 此外,该组件本身被列为FullTrust组件,用于在AppDomain。 琐碎的解决方法是删除完全信任PARAM。
在接下来的例子,针对插件加载主机的组件保护,ApplicationBase设置为甚至不需要存在一个随机路径(正常工作与PermissionState.Unrestricted
如果目录确实存在,同样的错误)。 AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
需要完全信任据我所知,所以我必须列出具有完全信任的组件 (我认为应该优先于应用程序域的受信任程序集上设置任何限制,而不是其他可能加载) -该组件可仅仅是“装载机”和插件将是该受限制的权限应该执行另一组件的一部分。 我必须定制AssemblyResolve因为目录不存在(或为空),因为我想在加载额外的组件的控制(比如,从byte[]
S)。
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;
}
}