该需求为: (The demand was for:

2019-10-19 04:29发布

我发现了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;
    }
}

Answer 1:

尝试通过创建存根手柄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);


文章来源: The demand was for: