Procedura dettagliata: Creazione di codice in scenari di attendibilità parzialeWalkthrough: Emitting Code in Partial Trust Scenarios

La reflection emit usa le stesse API in scenari di attendibilità sia parziale che completa, ma alcune funzionalità richiedono autorizzazioni speciali nel codice parzialmente attendibile.Reflection emit uses the same API set in full or partial trust, but some features require special permissions in partially trusted code. Inoltre, la reflection emit include una funzionalità, i metodi dinamici ospitati in modo anonimo, progettata per l'uso in situazioni di attendibilità parziale da parte di assembly trasparenti per la sicurezza.In addition, reflection emit has a feature, anonymously hosted dynamic methods, that is designed to be used with partial trust and by security-transparent assemblies.

Nota

Prima di .NET Framework 3.5, la creazione di codice richiedeva ReflectionPermission con il flag ReflectionPermissionFlag.ReflectionEmit.Before .NET Framework 3.5, emitting code required ReflectionPermission with the ReflectionPermissionFlag.ReflectionEmit flag. Questa autorizzazione è inclusa per impostazione predefinita nei set di autorizzazioni denominati FullTrust e Intranet, ma non nel set di autorizzazioni Internet.This permission is included by default in the FullTrust and Intranet named permission sets, but not in the Internet permission set. Di conseguenza, una libreria può essere usata con attendibilità parziale solo se in essa era presente l'attributo SecurityCriticalAttribute e veniva eseguito un metodo Assert per ReflectionEmit.Therefore, a library could be used from partial trust only if it had the SecurityCriticalAttribute attribute and also executed an Assert method for ReflectionEmit. Tali librerie richiedono un'attenta revisione della sicurezza perché eventuali errori nel codice potrebbe produrre delle vulnerabilità.Such libraries require careful security review because coding errors could result in security holes. .NET Framework 3.5 consente di generare codice in scenari con attendibilità parziale senza creare alcuna richiesta di sicurezza, poiché la generazione di codice non è implicitamente un'operazione con privilegi.The .NET Framework 3.5 allows code to be emitted in partial trust scenarios without issuing any security demands, because generating code is not inherently a privileged operation. Ovvero, il codice generato non dispone di ulteriori autorizzazioni rispetto all'assembly che lo genera.That is, the generated code has no more permissions than the assembly that emits it. Questo consente alle librerie che generano il codice di essere trasparenti per la sicurezza ed elimina la necessità di asserire ReflectionEmit, quindi la scrittura di una libreria protetta non richiede una revisione completa della sicurezza.This enables libraries that emit code to be security-transparent and removes the need to assert ReflectionEmit, so that writing a secure library does not require such a thorough security review.

Vengono illustrate le attività seguenti:This walkthrough illustrates the following tasks:

Per altre informazioni sulla generazione di codice in scenari di attendibilità parziale, vedere la sezione relativa ai problemi di sicurezza nella reflection emit.For more information about emitting code in partial trust scenarios, see Security Issues in Reflection Emit.

Per un elenco completo del codice riportato in queste procedure, vedere la sezione degli esempi alla fine di questa procedura dettagliata.For a complete listing of the code shown in these procedures, see the Example section at the end of this walkthrough.

Impostazione di percorsi parzialmente attendibiliSetting up Partially Trusted Locations

Le due procedure seguenti illustrano come impostare i percorsi da cui è possibile testare il codice con attendibilità parziale.The following two procedures show how to set up locations from which you can test code with partial trust.

  • La prima procedura spiega come creare un dominio dell'applicazione sandbox in cui vengono concesse autorizzazioni Internet al codice.The first procedure shows how to create a sandboxed application domain in which code is granted Internet permissions.

  • La seconda procedura illustra come aggiungere ReflectionPermission con il flag ReflectionPermissionFlag.RestrictedMemberAccess a un dominio dell'applicazione parzialmente attendibile, per consentire l'accesso ai dati privati negli assembly con attendibilità uguale o inferiore.The second procedure shows how to add ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag to a partially trusted application domain, to enable access to private data in assemblies of equal or lesser trust.

Creazione di domini dell'applicazione sandboxCreating Sandboxed Application Domains

Per creare un dominio applicazione in cui gli assembly sono eseguiti con attendibilità parziale, è necessario specificare il set di autorizzazioni da concedere agli assembly usando l'overload del metodo AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) per creare il dominio dell'applicazione.To create an application domain in which your assemblies run with partial trust, you must specify the set of permissions to be granted to the assemblies by using the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload to create the application domain. Il modo più semplice per specificare il set di concessioni è recuperare un set di autorizzazioni denominato dai criteri di sicurezza.The easiest way to specify the grant set is to retrieve a named permission set from security policy.

Nella procedura seguente viene creato un dominio dell'applicazione sandbox che esegue il codice con attendibilità parziale, per testare gli scenari in cui il codice generato può accedere solo ai membri pubblici dei tipi pubblici.The following procedure creates a sandboxed application domain that runs your code with partial trust, to test scenarios in which emitted code can access only public members of public types. Una procedura successiva illustra come aggiungere RestrictedMemberAccess, per testare scenari in cui il codice generato può accedere a tipi e membri non pubblici negli assembly a cui vengono concesse autorizzazioni uguali o inferiori.A subsequent procedure shows how to add RestrictedMemberAccess, to test scenarios in which emitted code can access nonpublic types and members in assemblies that are granted equal or lesser permissions.

Per creare un dominio dell'applicazione con attendibilità parzialeTo create an application domain with partial trust

  1. Creare un set di autorizzazioni da concedere agli assembly nel dominio dell'applicazione sandbox.Create a permission set to grant to the assemblies in the sandboxed application domain. In questo caso viene usato il set di autorizzazioni dell'area Internet.In this case, the permission set of the Internet zone is used.

    Evidence ev = new Evidence();
    ev.AddHostEvidence(new Zone(SecurityZone.Internet));
    PermissionSet pset = new NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev));
    
    Dim ev As New Evidence()
    ev.AddHostEvidence(new Zone(SecurityZone.Internet))
    Dim pset As New NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev))
    
  2. Creare un oggetto AppDomainSetup per inizializzare il dominio dell'applicazione con un percorso dell'applicazione.Create an AppDomainSetup object to initialize the application domain with an application path.

    Importante

    Per semplicità, questo esempio di codice usa la cartella corrente.For simplicity, this code example uses the current folder. Per eseguire codice realmente proveniente da Internet, usare una cartella separata per il codice non attendibile, come descritto nella procedura relativa all'esecuzione di codice parzialmente attendibile in un oggetto sandbox.To run code that actually comes from the Internet, use a separate folder for the untrusted code, as described in How to: Run Partially Trusted Code in a Sandbox.

    AppDomainSetup adSetup = new AppDomainSetup();
    adSetup.ApplicationBase = ".";
    
    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = "."
    
  3. Creare il dominio dell'applicazione, specificando le informazioni di configurazione del dominio dell'applicazione e il set di concessioni per tutti gli assembly eseguiti nel dominio dell'applicazione.Create the application domain, specifying the application domain setup information and the grant set for all assemblies that execute in the application domain.

    AppDomain ad = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, null);
    
    Dim ad As AppDomain = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, Nothing)
    

    L'ultimo parametro dell'overload del metodo AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) consente di specificare un set di assembly a cui deve essere concessa l'attendibilità totale, anziché il set di concessioni del dominio dell'applicazione.The last parameter of the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload enables you to specify a set of assemblies that are to be granted full trust, instead of the grant set of the application domain. Non è necessario specificare gli assembly .NET Framework usati dall'applicazione, perché si trovano nella Global Assembly Cache.You do not have to specify the .NET Framework assemblies that your application uses, because those assemblies are in the global assembly cache. Gli assembly nella Global Assembly Cache sono sempre completamente attendibili.Assemblies in the global assembly cache are always fully trusted. È possibile usare questo parametro per specificare assembly con nome sicuro che non sono presenti nella Global Assembly Cache.You can use this parameter to specify strong-named assemblies that are not in the global assembly cache.

Aggiunta di RestrictedMemberAccess ai domini sandboxAdding RestrictedMemberAccess to Sandboxed Domains

Le applicazioni host possono consentire ai metodi dinamici ospitati in modo anonimo di accedere ai dati privati negli assembly con livelli di attendibilità uguali o inferiori a quelli dell'assembly che genera il codice.Host applications can allow anonymously hosted dynamic methods to have access to private data in assemblies that have trust levels equal to or less than the trust level of the assembly that emits the code. Per abilitare la possibilità limitata di ignorare i controlli di visibilità just-in-time (JIT), l'applicazione host aggiunge un oggetto ReflectionPermission con il flag ReflectionPermissionFlag.RestrictedMemberAccess (RMA) al set di concessioni.To enable this restricted ability to skip just-in-time (JIT) visibility checks, the host application adds a ReflectionPermission object with the ReflectionPermissionFlag.RestrictedMemberAccess (RMA) flag to the grant set.

Ad esempio, un host può concedere alle applicazioni Internet autorizzazioni Internet più RMA, in modo tale che un'applicazione Internet sia in grado di generare codice che accede ai dati privati nei propri assembly.For example, a host might grant Internet applications Internet permissions plus RMA, so that an Internet application can emit code that accesses private data in its own assemblies. Poiché l'accesso è limitato agli assembly con attendibilità uguale o minore, un'applicazione Internet non può accedere a membri di assembly completamente attendibili, ad esempio gli assembly .NET Framework.Because the access is limited to assemblies of equal or lesser trust, an Internet application cannot access members of fully trusted assemblies such as .NET Framework assemblies.

Nota

Per evitare l'elevazione dei privilegi, le informazioni sullo stack per l'assembly di creazione vengono incluse quando si creano metodi dinamici ospitati in modo anonimo.To prevent elevation of privilege, stack information for the emitting assembly is included when anonymously hosted dynamic methods are constructed. Quando il metodo viene richiamato, vengono controllate le informazioni sullo stack.When the method is invoked, the stack information is checked. Di conseguenza, un metodo dinamico ospitato in modo anonimo richiamato da codice completamente attendibile è comunque limitato al livello di attendibilità dell'assembly di creazione.Thus, an anonymously hosted dynamic method that is invoked from fully trusted code is still limited to the trust level of the emitting assembly.

Per creare un dominio dell'applicazione con attendibilità parziale più RMATo create an application domain with partial trust plus RMA

  1. Creare un nuovo oggetto ReflectionPermission con il flag RestrictedMemberAccess (RMA) e usare il metodo PermissionSet.SetPermission per aggiungere l'autorizzazione al set di concessioni.Create a new ReflectionPermission object with the RestrictedMemberAccess (RMA) flag, and use the PermissionSet.SetPermission method to add the permission to the grant set.

    pset.SetPermission(
        new ReflectionPermission(
            ReflectionPermissionFlag.RestrictedMemberAccess));
    
    pset.SetPermission( _
        New ReflectionPermission( _
            ReflectionPermissionFlag.RestrictedMemberAccess))
    

    Il metodo AddPermission aggiunge l'autorizzazione al set di concessioni, se non è già inclusa.The AddPermission method adds the permission to the grant set if it is not already included. Se l'autorizzazione è già inclusa nel set di concessioni, i flag specificati vengono aggiunti all'autorizzazione esistente.If the permission is already included in the grant set, the specified flags are added to the existing permission.

    Nota

    RMA è una funzionalità dei metodi dinamici ospitati in modo anonimo.RMA is a feature of anonymously hosted dynamic methods. Quando i metodi dinamici comuni ignorano i controlli di visibilità JIT, il codice generato richiede l'attendibilità totale.When ordinary dynamic methods skip JIT visibility checks, the emitted code requires full trust.

  2. Creare il dominio dell'applicazione, specificando le informazioni di configurazione del dominio dell'applicazione e il set di concessioni.Create the application domain, specifying the application domain setup information and the grant set.

    ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);
    
    ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)
    

Esecuzione di codice nei domini dell'applicazione sandboxRunning Code in Sandboxed Application Domains

La procedura seguente spiega come definire una classe usando metodi che possono essere eseguiti in un dominio dell'applicazione, come creare un'istanza della classe nel dominio e come eseguire i relativi metodi.The following procedure explains how to define a class by using methods that can be executed in an application domain, how to create an instance of the class in the domain, and how to execute its methods.

Per definire ed eseguire un metodo in un dominio dell'applicazioneTo define and execute a method in an application domain

  1. Definire una classe che deriva da MarshalByRefObject.Define a class that derives from MarshalByRefObject. Ciò consente di creare istanze della classe in altri domini dell'applicazione e di effettuare chiamate al metodo tra i limiti del dominio dell'applicazione.This enables you to create instances of the class in other application domains and to make method calls across application domain boundaries. La classe di questo esempio è denominata Worker.The class in this example is named Worker.

    public class Worker : MarshalByRefObject
    {
    
    Public Class Worker
        Inherits MarshalByRefObject
    
  2. Definire un metodo pubblico che contenga il codice da eseguire.Define a public method that contains the code you want to execute. In questo esempio, il codice genera un metodo dinamico semplice, crea un delegato per eseguire il metodo e richiama il delegato.In this example, the code emits a simple dynamic method, creates a delegate to execute the method, and invokes the delegate.

    public void SimpleEmitDemo()
    {
        DynamicMethod meth = new DynamicMethod("", null, null);
        ILGenerator il = meth.GetILGenerator();
        il.EmitWriteLine("Hello, World!");
        il.Emit(OpCodes.Ret);
    
        Test1 t1 = (Test1) meth.CreateDelegate(typeof(Test1));
        t1();
    }
    
    Public Sub SimpleEmitDemo()
    
        Dim meth As DynamicMethod = new DynamicMethod("", Nothing, Nothing)
        Dim il As ILGenerator = meth.GetILGenerator()
        il.EmitWriteLine("Hello, World!")
        il.Emit(OpCodes.Ret)
    
        Dim t1 As Test1 = CType(meth.CreateDelegate(GetType(Test1)), Test1)
        t1()
    End Sub
    
  3. Nel programma principale ottenere il nome visualizzato dell'assembly.In your main program, get the display name of your assembly. Questo nome viene usato quando si creano istanze della classe Worker nel dominio dell'applicazione sandbox.This name is used when you create instances of the Worker class in the sandboxed application domain.

    String asmName = typeof(Worker).Assembly.FullName;
    
    Dim asmName As String = GetType(Worker).Assembly.FullName
    
  4. Nel programma principale creare un dominio dell'applicazione sandbox, come descritto nella prima procedura in questa procedura dettagliata.In your main program, create a sandboxed application domain, as described in the first procedure in this walkthrough. Non è necessario aggiungere autorizzazioni al set di autorizzazioni Internet, poiché il metodo SimpleEmitDemo usa solo metodi pubblici.You do not have to add any permissions to the Internet permission set, because the SimpleEmitDemo method uses only public methods.

  5. Nel programma principale creare un'istanza della classe Worker nel dominio dell'applicazione sandbox.In your main program, create an instance of the Worker class in the sandboxed application domain.

    Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");
    
    Dim w As Worker = _
        CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)
    

    Il metodo CreateInstanceAndUnwrap crea l'oggetto nel dominio dell'applicazione di destinazione e restituisce un proxy che può essere usato per chiamare le proprietà e metodi dell'oggetto.The CreateInstanceAndUnwrap method creates the object in the target application domain and returns a proxy that can be used to call the properties and methods of the object.

    Nota

    Se questo codice viene utilizzato in Visual Studio, è necessario modificare il nome della classe per includere lo spazio dei nomi.If you use this code in Visual Studio, you must change the name of the class to include the namespace. Per impostazione predefinita, lo spazio dei nomi è il nome del progetto.By default, the namespace is the name of the project. Ad esempio, se il progetto è "PartialTrust", il nome della classe deve essere "PartialTrust.Worker".For example, if the project is "PartialTrust", the class name must be "PartialTrust.Worker".

  6. Aggiungere il codice per chiamare il metodo SimpleEmitDemo .Add code to call the SimpleEmitDemo method. La chiamata viene sottoposta a marshalling entro i limiti del dominio dell'applicazione e il codice viene eseguito nel dominio dell'applicazione sandbox.The call is marshaled across the application domain boundary, and the code is executed in the sandboxed application domain.

    w.SimpleEmitDemo();
    
    w.SimpleEmitDemo()
    

Uso dei metodi dinamici ospitati in modo anonimoUsing Anonymously Hosted Dynamic Methods

I metodi dinamici ospitati in modo anonimo sono associati a un assembly trasparente messo a disposizione dal sistema.Anonymously hosted dynamic methods are associated with a transparent assembly that is provided by the system. Di conseguenza, il codice che contengono è trasparente.Therefore, the code they contain is transparent. I metodi dinamici comuni, d'altra parte, devono essere associati a un modulo esistente, specificato direttamente o derivato da un tipo associato, e ricevono il livello di sicurezza da tale modulo.Ordinary dynamic methods, on the other hand, must be associated with an existing module (whether directly specified or inferred from an associated type), and take their security level from that module.

Nota

L'unico modo di associare un metodo dinamico all'assembly che offre l'hosting anonimo è usare i costruttori descritti nella procedura seguente.The only way to associate a dynamic method with the assembly that provides anonymous hosting is to use the constructors that are described in the following procedure. Non è possibile specificare in modo esplicito un modulo nell'assembly di hosting anonimo.You cannot explicitly specify a module in the anonymous hosting assembly.

I metodi dinamici comuni hanno accesso ai membri interni del modulo a cui sono associati o ai membri privati del tipo a cui sono associati.Ordinary dynamic methods have access to the internal members of the module they are associated with, or to the private members of the type they are associated with. Poiché i metodi dinamici ospitati in modo anonimo sono isolati dall'altro codice, non hanno accesso ai dati privati.Because anonymously hosted dynamic methods are isolated from other code, they do not have access to private data. Usano tuttavia una possibilità limitata per ignorare i controlli di visibilità JIT in modo da ottenere l'accesso ai dati privati.However, they do have a restricted ability to skip JIT visibility checks to gain access to private data. Tale possibilità è limitata agli assembly con livelli di attendibilità uguali o inferiori a quello dell'assembly che genera il codice.This ability is limited to assemblies that have trust levels equal to or less than the trust level of the assembly that emits the code.

Per evitare l'elevazione dei privilegi, le informazioni sullo stack per l'assembly di creazione vengono incluse quando si creano metodi dinamici ospitati in modo anonimo.To prevent elevation of privilege, stack information for the emitting assembly is included when anonymously hosted dynamic methods are constructed. Quando il metodo viene richiamato, vengono controllate le informazioni sullo stack.When the method is invoked, the stack information is checked. Un metodo dinamico ospitato in modo anonimo richiamato da un codice completamente attendibile è comunque limitato al livello di attendibilità dell'assembly in cui è stato creato.An anonymously hosted dynamic method that is invoked from fully trusted code is still limited to the trust level of the assembly that emitted it.

Per usare i metodi dinamici ospitati in modo anonimoTo use anonymously hosted dynamic methods

  • Creare un metodo dinamico ospitato in modo anonimo usando un costruttore che non specifica un modulo o un tipo associato.Create an anonymously hosted dynamic method by using a constructor that does not specify an associated module or type.

    DynamicMethod meth = new DynamicMethod("", null, null);
    ILGenerator il = meth.GetILGenerator();
    il.EmitWriteLine("Hello, World!");
    il.Emit(OpCodes.Ret);
    
    Dim meth As DynamicMethod = new DynamicMethod("", Nothing, Nothing)
    Dim il As ILGenerator = meth.GetILGenerator()
    il.EmitWriteLine("Hello, World!")
    il.Emit(OpCodes.Ret)
    

    Se un metodo dinamico ospitato in modo anonimo usa solo tipi e metodi pubblici, non richiede l'accesso limitato al membro e non è necessario ignorare i controlli di visibilità JIT.If an anonymously hosted dynamic method uses only public types and methods, it does not require restricted member access and does not have to skip JIT visibility checks.

    Non sono richieste autorizzazioni speciali per generare un metodo dinamico, ma per il codice generato sono necessarie le autorizzazioni obbligatorie per i tipi e i metodi usati.No special permissions are required to emit a dynamic method, but the emitted code requires the permissions that are demanded by the types and methods it uses. Ad esempio, se il codice generato chiama un metodo che accede a un file, richiede FileIOPermission.For example, if the emitted code calls a method that accesses a file, it requires FileIOPermission. Se il livello di attendibilità non include tale autorizzazione, viene generata un'eccezione di sicurezza quando viene eseguito il codice generato.If the trust level does not include that permission, a security exception is thrown when the emitted code is executed. Il codice riportato di seguito genera un metodo dinamico che usa solo il metodo Console.WriteLine.The code shown here emits a dynamic method that uses only the Console.WriteLine method. Di conseguenza, il codice può essere eseguito da percorsi parzialmente attendibili.Therefore, the code can be executed from partially trusted locations.

  • In alternativa, creare un metodo dinamico ospitato in modo anonimo con la possibilità limitata di ignorare i controlli di visibilità JIT, usando il costruttore DynamicMethod(String, Type, Type[], Boolean) e specificando true per il parametro restrictedSkipVisibility.Alternatively, create an anonymously hosted dynamic method with restricted ability to skip JIT visibility checks, by using the DynamicMethod(String, Type, Type[], Boolean) constructor and specifying true for the restrictedSkipVisibility parameter.

    DynamicMethod meth = new DynamicMethod("",
                                           typeof(char),
                                           new Type[] { typeof(String) },
                                           true);
    
    Dim meth As New DynamicMethod("", _
                                  GetType(Char), _
                                  New Type() {GetType(String)}, _
                                  True)
    

    La limitazione consiste nel fatto che il metodo dinamico ospitato in modo anonimo può accedere ai dati privati solo negli assembly con livelli di attendibilità uguali o inferiori a quello dell'assembly di creazione.The restriction is that the anonymously hosted dynamic method can access private data only in assemblies with trust levels equal to or less than the trust level of the emitting assembly. Ad esempio, se il metodo dinamico è in esecuzione con attendibilità Internet, può accedere ai dati privati in altri assembly in esecuzione con attendibilità Internet, ma non può accedere ai dati privati degli assembly .NET Framework.For example, if the dynamic method is executing with Internet trust, it can access private data in other assemblies that are also executing with Internet trust, but it cannot access private data of .NET Framework assemblies. Gli assembly .NET Framework sono installati nella Global Assembly Cache e sono sempre completamente attendibili..NET Framework assemblies are installed in the global assembly cache and are always fully trusted.

    I metodi dinamici ospitati in modo anonimo possono usare questa possibilità limitata di ignorare i controlli di visibilità JIT solo se l'applicazione host concede ReflectionPermission con il flag ReflectionPermissionFlag.RestrictedMemberAccess.Anonymously hosted dynamic methods can use this restricted ability to skip JIT visibility checks only if the host application grants ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag. La richiesta di questa autorizzazione viene effettuata quando viene richiamato il metodo.The demand for this permission is made when the method is invoked.

    Nota

    Le informazioni sullo stack di chiamate per l'assembly di creazione vengono incluse quando viene costruito il metodo dinamico.Call stack information for the emitting assembly is included when the dynamic method is constructed. Di conseguenza, la richiesta viene effettuata facendo riferimento alle autorizzazioni dell'assembly di creazione anziché a quelle dell'assembly che richiama il metodo.Therefore, the demand is made against the permissions of the emitting assembly instead of the assembly that invokes the method. Ciò impedisce che il codice generato venga eseguito con autorizzazioni elevate.This prevents the emitted code from being executed with elevated permissions.

    L'esempio di codice completo alla fine di questa procedura dettagliata illustra l'uso e le limitazioni dell'accesso limitato al membro.The complete code example at the end of this walkthrough demonstrates the use and limitations of restricted member access. La relativa classe Worker include un metodo in grado di creare metodi dinamici ospitati in modo anonimo con o senza la possibilità limitata di ignorare i controlli di visibilità e l'esempio illustra il risultato dell'esecuzione di questo metodo nei domini dell'applicazione con diversi livelli di attendibilità.Its Worker class includes a method that can create anonymously hosted dynamic methods with or without the restricted ability to skip visibility checks, and the example shows the result of executing this method in application domains that have different trust levels.

    Nota

    La possibilità limitata di ignorare i controlli di visibilità è una funzionalità di metodi dinamici ospitati in modo anonimo.The restricted ability to skip visibility checks is a feature of anonymously hosted dynamic methods. Quando i metodi dinamici comuni ignorano i controlli di visibilità JIT, deve essere concessa l'attendibilità totale.When ordinary dynamic methods skip JIT visibility checks, they must be granted full trust.

EsempioExample

DescrizioneDescription

Nell'esempio di codice riportato di seguito viene illustrato l'uso del flag RestrictedMemberAccess per consentire ai metodi dinamici ospitati in modo anonimo di ignorare i controlli di visibilità JIT, ma solo quando il membro di destinazione è un livello uguale o inferiore di attendibilità rispetto all'assembly che genera il codice.The following code example demonstrates the use of the RestrictedMemberAccess flag to allow anonymously hosted dynamic methods to skip JIT visibility checks, but only when the target member is at an equal or lower level of trust than the assembly that emits the code.

Nell'esempio viene definita una classe Worker che può essere sottoposta a marshalling entro i limiti del dominio dell'applicazione.The example defines a Worker class that can be marshaled across application domain boundaries. La classe ha due overload del metodo AccessPrivateMethod che generano ed eseguono i metodi dinamici.The class has two AccessPrivateMethod method overloads that emit and execute dynamic methods. Il primo overload genera un metodo dinamico che chiama il metodo privato PrivateMethod della classe Worker e può generare il metodo dinamico con o senza controlli di visibilità JIT.The first overload emits a dynamic method that calls the private PrivateMethod method of the Worker class, and it can emit the dynamic method with or without JIT visibility checks. Il secondo overload genera un metodo dinamico che accede a una proprietà internal (proprietà Friend in Visual Basic) della classe String.The second overload emits a dynamic method that accesses an internal property (Friend property in Visual Basic) of the String class.

L'esempio usa un metodo helper per creare un set di concessioni limitato alle autorizzazioni Internet, quindi crea un dominio dell'applicazione usando l'overload del metodo AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) per specificare che tutto il codice eseguito nel dominio usa questo set di concessioni.The example uses a helper method to create a grant set limited to Internet permissions, and then creates an application domain, using the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload to specify that all code that executes in the domain uses this grant set. Nell'esempio viene creata un'istanza della classe Worker nel dominio dell'applicazione e viene eseguito due volte il metodo AccessPrivateMethod.The example creates an instance of the Worker class in the application domain, and executes the AccessPrivateMethod method two times.

  • La prima volta che il metodo AccessPrivateMethod viene eseguito, vengono applicati i controlli di visibilità JIT.The first time the AccessPrivateMethod method is executed, JIT visibility checks are enforced. Il metodo dinamico ha esito negativo quando viene richiamato, perché i controlli di visibilità JIT impediscono l'accesso al metodo privato.The dynamic method fails when it is invoked, because JIT visibility checks prevent it from accessing the private method.

  • La seconda volta che il metodo AccessPrivateMethod viene eseguito, i controlli di visibilità JIT vengono ignorati.The second time the AccessPrivateMethod method is executed, JIT visibility checks are skipped. Il metodo dinamico ha esito negativo quando viene compilato, poiché il set di concessioni Internet non concede autorizzazioni sufficienti per ignorare i controlli di visibilità.The dynamic method fails when it is compiled, because the Internet grant set does not grant sufficient permissions to skip visibility checks.

Nell'esempio viene aggiunto ReflectionPermission con ReflectionPermissionFlag.RestrictedMemberAccess al set di concessioni.The example adds ReflectionPermission with ReflectionPermissionFlag.RestrictedMemberAccess to the grant set. Viene quindi creato un secondo dominio, specificando che a tutto il codice eseguito nel dominio vengano concesse le autorizzazioni del nuovo set di concessioni.The example then creates a second domain, specifying that all code that executes in the domain is granted the permissions in the new grant set. Viene creata un'istanza della classe Worker nel nuovo dominio dell'applicazione e vengono eseguiti entrambi gli overload del metodo AccessPrivateMethod.The example creates an instance of the Worker class in the new application domain, and executes both overloads of the AccessPrivateMethod method.

  • Viene eseguito il primo overload del metodo AccessPrivateMethod e i controlli di visibilità JIT vengono ignorati.The first overload of the AccessPrivateMethod method is executed, and JIT visibility checks are skipped. Il metodo dinamico viene compilato ed eseguito correttamente, poiché l'assembly che genera il codice è lo stesso assembly che contiene il metodo privato.The dynamic method compiles and executes successfully, because the assembly that emits the code is the same as the assembly that contains the private method. Di conseguenza, i livelli di attendibilità sono uguali.Therefore, the trust levels are equal. Se l'applicazione che contiene la classe Worker ha diversi assembly, l'esito del processo sarà lo stesso per tutti gli assembly, poiché sono tutti allo stesso livello di attendibilità.If the application that contains the Worker class had several assemblies, the same process would succeed for any one of those assemblies, because they would all be at the same trust level.

  • Viene eseguito il secondo overload del metodo AccessPrivateMethod e i controlli di visibilità JIT vengono di nuovo ignorati.The second overload of the AccessPrivateMethod method is executed, and again JIT visibility checks are skipped. Questa volta il metodo dinamico ha esito negativo quando viene compilato, perché tenta di accedere alla internal FirstChar proprietà della String classe.This time the dynamic method fails when it is compiled, because it tries to access the internal FirstChar property of the String class. L'assembly che contiene la classe String è completamente attendibile.The assembly that contains the String class is fully trusted. Si trova quindi a un livello di attendibilità superiore rispetto all'assembly che genera il codice.Therefore, it is at a higher level of trust than the assembly that emits the code.

Questo confronto spiega come ReflectionPermissionFlag.RestrictedMemberAccess consente al codice parzialmente attendibile di ignorare i controlli di visibilità per altro codice parzialmente attendibile senza compromettere la sicurezza del codice attendibile.This comparison shows how ReflectionPermissionFlag.RestrictedMemberAccess enables partially trusted code to skip visibility checks for other partially trusted code without compromising the security of trusted code.

CodiceCode

using System;
using System.Reflection.Emit;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Collections;
using System.Diagnostics;

// This code example works properly only if it is run from a fully
// trusted location, such as your local computer.

// Delegates used to execute the dynamic methods.
//
public delegate void Test(Worker w);
public delegate void Test1();
public delegate char Test2(String instance);

// The Worker class must inherit MarshalByRefObject so that its public
// methods can be invoked across application domain boundaries.
//
public class Worker : MarshalByRefObject
{
    private void PrivateMethod()
    {
        Console.WriteLine("Worker.PrivateMethod()");
    }

    public void SimpleEmitDemo()
    {
        DynamicMethod meth = new DynamicMethod("", null, null);
        ILGenerator il = meth.GetILGenerator();
        il.EmitWriteLine("Hello, World!");
        il.Emit(OpCodes.Ret);

        Test1 t1 = (Test1) meth.CreateDelegate(typeof(Test1));
        t1();
    }

    // This overload of AccessPrivateMethod emits a dynamic method and
    // specifies whether to skip JIT visiblity checks. It creates a
    // delegate for the method and invokes the delegate. The dynamic
    // method calls a private method of the Worker class.
    public void AccessPrivateMethod(bool restrictedSkipVisibility)
    {
        // Create an unnamed dynamic method that has no return type,
        // takes one parameter of type Worker, and optionally skips JIT
        // visiblity checks.
        DynamicMethod meth = new DynamicMethod(
            "",
            null,
            new Type[] { typeof(Worker) },
            restrictedSkipVisibility);

        // Get a MethodInfo for the private method.
        MethodInfo pvtMeth = typeof(Worker).GetMethod("PrivateMethod",
            BindingFlags.NonPublic | BindingFlags.Instance);

        // Get an ILGenerator and emit a body for the dynamic method.
        ILGenerator il = meth.GetILGenerator();

        // Load the first argument, which is the target instance, onto the
        // execution stack, call the private method, and return.
        il.Emit(OpCodes.Ldarg_0);
        il.EmitCall(OpCodes.Call, pvtMeth, null);
        il.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method, and
        // invoke it.
        try
        {
            Test t = (Test) meth.CreateDelegate(typeof(Test));
            try
            {
                t(this);
            }
            catch (Exception ex)
            {
                Console.WriteLine("{0} was thrown when the delegate was invoked.",
                    ex.GetType().Name);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("{0} was thrown when the delegate was compiled.",
                ex.GetType().Name);
        }
    }

    // This overload of AccessPrivateMethod emits a dynamic method that takes
    // a string and returns the first character, using a private field of the
    // String class. The dynamic method skips JIT visiblity checks.
    public void AccessPrivateMethod()
    {
        DynamicMethod meth = new DynamicMethod("",
                                               typeof(char),
                                               new Type[] { typeof(String) },
                                               true);

        // Get a MethodInfo for the 'get' accessor of the private property.
        PropertyInfo pi = typeof(System.String).GetProperty(
            "FirstChar",
            BindingFlags.NonPublic | BindingFlags.Instance);
        MethodInfo pvtMeth = pi.GetGetMethod(true);

        // Get an ILGenerator and emit a body for the dynamic method.
        ILGenerator il = meth.GetILGenerator();

        // Load the first argument, which is the target string, onto the
        // execution stack, call the 'get' accessor to put the result onto
        // the execution stack, and return.
        il.Emit(OpCodes.Ldarg_0);
        il.EmitCall(OpCodes.Call, pvtMeth, null);
        il.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method, and
        // invoke it.
        try
        {
            Test2 t = (Test2) meth.CreateDelegate(typeof(Test2));
            char first = t("Hello, World!");
            Console.WriteLine("{0} is the first character.", first);
        }
        catch (Exception ex)
        {
            Console.WriteLine("{0} was thrown when the delegate was compiled.",
                ex.GetType().Name);
        }
    }

    // The entry point for the code example.
    static void Main()
    {
        // Get the display name of the executing assembly, to use when
        // creating objects to run code in application domains.
        String asmName = typeof(Worker).Assembly.FullName;

        // Create the permission set to grant to other assemblies. In this
        // case they are the permissions found in the Internet zone.
        Evidence ev = new Evidence();
        ev.AddHostEvidence(new Zone(SecurityZone.Internet));
        PermissionSet pset = new NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev));

        // For simplicity, set up the application domain to use the
        // current path as the application folder, so the same executable
        // can be used in both trusted and untrusted scenarios. Normally
        // you would not do this with real untrusted code.
        AppDomainSetup adSetup = new AppDomainSetup();
        adSetup.ApplicationBase = ".";

        // Create an application domain in which all code that executes is
        // granted the permissions of an application run from the Internet.
        AppDomain ad = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, null);

        // Create an instance of the Worker class in the partially trusted
        // domain. Note: If you build this code example in Visual Studio,
        // you must change the name of the class to include the default
        // namespace, which is the project name. For example, if the project
        // is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");

        // Emit a simple dynamic method that prints "Hello, World!"
        w.SimpleEmitDemo();

        // Emit and invoke a dynamic method that calls a private method
        // of Worker, with JIT visibility checks enforced. The call fails
        // when the delegate is invoked.
        w.AccessPrivateMethod(false);

        // Emit and invoke a dynamic method that calls a private method
        // of Worker, skipping JIT visibility checks. The call fails when
        // the method is invoked.
        w.AccessPrivateMethod(true);

        // Unload the application domain. Add RestrictedMemberAccess to the
        // grant set, and use it to create an application domain in which
        // partially trusted code can call private members, as long as the
        // trust level of those members is equal to or lower than the trust
        // level of the partially trusted code.
        AppDomain.Unload(ad);
        pset.SetPermission(
            new ReflectionPermission(
                ReflectionPermissionFlag.RestrictedMemberAccess));
        ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);

        // Create an instance of the Worker class in the partially trusted
        // domain.
        w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");

        // Again, emit and invoke a dynamic method that calls a private method
        // of Worker, skipping JIT visibility checks. This time compilation
        // succeeds because of the grant for RestrictedMemberAccess.
        w.AccessPrivateMethod(true);

        // Finally, emit and invoke a dynamic method that calls an internal
        // method of the String class. The call fails, because the trust level
        // of the assembly that contains String is higher than the trust level
        // of the assembly that emits the dynamic method.
        w.AccessPrivateMethod();
    }
}

/* This code example produces the following output:

Hello, World!
MethodAccessException was thrown when the delegate was invoked.
MethodAccessException was thrown when the delegate was invoked.
Worker.PrivateMethod()
MethodAccessException was thrown when the delegate was compiled.
 */
Imports System.Reflection.Emit
Imports System.Reflection
Imports System.Security
Imports System.Security.Permissions
Imports System.Security.Policy
Imports System.Collections
Imports System.Diagnostics

' This code example works properly only if it is run from a fully 
' trusted location, such as your local computer.

' Delegates used to execute the dynamic methods.
'
Public Delegate Sub Test(ByVal w As Worker)
Public Delegate Sub Test1()
Public Delegate Function Test2(ByVal instance As String) As Char

' The Worker class must inherit MarshalByRefObject so that its public 
' methods can be invoked across application domain boundaries.
'
Public Class Worker
    Inherits MarshalByRefObject

    Private Sub PrivateMethod()
        Console.WriteLine("Worker.PrivateMethod()")
    End Sub

    Public Sub SimpleEmitDemo()

        Dim meth As DynamicMethod = new DynamicMethod("", Nothing, Nothing)
        Dim il As ILGenerator = meth.GetILGenerator()
        il.EmitWriteLine("Hello, World!")
        il.Emit(OpCodes.Ret)

        Dim t1 As Test1 = CType(meth.CreateDelegate(GetType(Test1)), Test1)
        t1()
    End Sub

    ' This overload of AccessPrivateMethod emits a dynamic method and
    ' specifies whether to skip JIT visiblity checks. It creates a 
    ' delegate for the method and invokes the delegate. The dynamic 
    ' method calls a private method of the Worker class.
    Overloads Public Sub AccessPrivateMethod( _
                       ByVal restrictedSkipVisibility As Boolean)

        ' Create an unnamed dynamic method that has no return type,
        ' takes one parameter of type Worker, and optionally skips JIT
        ' visiblity checks.
        Dim meth As New DynamicMethod("", _
                                      Nothing, _
                                      New Type() {GetType(Worker)}, _
                                      restrictedSkipVisibility)

        ' Get a MethodInfo for the private method.
        Dim pvtMeth As MethodInfo = GetType(Worker).GetMethod( _
            "PrivateMethod", _
            BindingFlags.NonPublic Or BindingFlags.Instance)

        ' Get an ILGenerator and emit a body for the dynamic method.
        Dim il As ILGenerator = meth.GetILGenerator()

        ' Load the first argument, which is the target instance, onto the
        ' execution stack, call the private method, and return.
        il.Emit(OpCodes.Ldarg_0)
        il.EmitCall(OpCodes.Call, pvtMeth, Nothing)
        il.Emit(OpCodes.Ret)

        ' Create a delegate that represents the dynamic method, and 
        ' invoke it. 
        Try
            Dim t As Test = CType(meth.CreateDelegate(GetType(Test)), Test)
            Try
                t(Me)
            Catch ex As Exception
                Console.WriteLine("{0} was thrown when the delegate was invoked.", _
                    ex.GetType().Name)
            End Try
        Catch ex As Exception
            Console.WriteLine("{0} was thrown when the delegate was compiled.", _
                ex.GetType().Name)
        End Try

    End Sub


    ' This overload of AccessPrivateMethod emits a dynamic method that takes
    ' a string and returns the first character, using a private field of the 
    ' String class. The dynamic method skips JIT visiblity checks.
    Overloads Public Sub AccessPrivateMethod()

        Dim meth As New DynamicMethod("", _
                                      GetType(Char), _
                                      New Type() {GetType(String)}, _
                                      True)

        ' Get a MethodInfo for the 'get' accessor of the private property.
        Dim pi As PropertyInfo = GetType(String).GetProperty( _
            "FirstChar", _
            BindingFlags.NonPublic Or BindingFlags.Instance)
        Dim pvtMeth As MethodInfo = pi.GetGetMethod(True)

        ' Get an ILGenerator and emit a body for the dynamic method.
        Dim il As ILGenerator = meth.GetILGenerator()

        ' Load the first argument, which is the target string, onto the
        ' execution stack, call the 'get' accessor to put the result onto 
        ' the execution stack, and return.
        il.Emit(OpCodes.Ldarg_0)
        il.EmitCall(OpCodes.Call, pvtMeth, Nothing)
        il.Emit(OpCodes.Ret)

        ' Create a delegate that represents the dynamic method, and 
        ' invoke it. 
        Try
            Dim t As Test2 = CType(meth.CreateDelegate(GetType(Test2)), Test2)
            Dim first As Char = t("Hello, World!")
            Console.WriteLine("{0} is the first character.", first)
        Catch ex As Exception
            Console.WriteLine("{0} was thrown when the delegate was compiled.", _
                ex.GetType().Name)
        End Try

    End Sub
End Class

Friend Class Example

    ' The entry point for the code example.
    Shared Sub Main()

        ' Get the display name of the executing assembly, to use when
        ' creating objects to run code in application domains.
        Dim asmName As String = GetType(Worker).Assembly.FullName

        ' Create the permission set to grant to other assemblies. In this
        ' case they are the permissions found in the Internet zone.
        Dim ev As New Evidence()
        ev.AddHostEvidence(new Zone(SecurityZone.Internet))
        Dim pset As New NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev))

        ' For simplicity, set up the application domain to use the 
        ' current path as the application folder, so the same executable
        ' can be used in both trusted and untrusted scenarios. Normally
        ' you would not do this with real untrusted code.
        Dim adSetup As New AppDomainSetup()
        adSetup.ApplicationBase = "."

        ' Create an application domain in which all code that executes is 
        ' granted the permissions of an application run from the Internet.
        Dim ad As AppDomain = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, Nothing)

        ' Create an instance of the Worker class in the partially trusted 
        ' domain. Note: If you build this code example in Visual Studio, 
        ' you must change the name of the class to include the default 
        ' namespace, which is the project name. For example, if the project
        ' is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
        Dim w As Worker = _
            CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)

        ' Emit a simple dynamic method that prints "Hello, World!"
        w.SimpleEmitDemo()

        ' Emit and invoke a dynamic method that calls a private method
        ' of Worker, with JIT visibility checks enforced. The call fails 
        ' when the delegate is invoked.
        w.AccessPrivateMethod(False)

        ' Emit and invoke a dynamic method that calls a private method
        ' of Worker, skipping JIT visibility checks. The call fails when
        ' the method is compiled.
        w.AccessPrivateMethod(True)


        ' Unload the application domain. Add RestrictedMemberAccess to the
        ' grant set, and use it to create an application domain in which
        ' partially trusted code can call private members, as long as the 
        ' trust level of those members is equal to or lower than the trust 
        ' level of the partially trusted code. 
        AppDomain.Unload(ad)
        pset.SetPermission( _
            New ReflectionPermission( _
                ReflectionPermissionFlag.RestrictedMemberAccess))
        ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)

        ' Create an instance of the Worker class in the partially trusted 
        ' domain. 
        w = CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)

        ' Again, emit and invoke a dynamic method that calls a private method
        ' of Worker, skipping JIT visibility checks. This time compilation 
        ' succeeds because of the grant for RestrictedMemberAccess.
        w.AccessPrivateMethod(True)

        ' Finally, emit and invoke a dynamic method that calls an internal 
        ' method of the String class. The call fails, because the trust level
        ' of the assembly that contains String is higher than the trust level
        ' of the assembly that emits the dynamic method.
        w.AccessPrivateMethod()

    End Sub
End Class

' This code example produces the following output:
'
'Hello, World!
'MethodAccessException was thrown when the delegate was invoked.
'MethodAccessException was thrown when the delegate was invoked.
'Worker.PrivateMethod()
'MethodAccessException was thrown when the delegate was compiled.
' 

Compilazione del codiceCompiling the Code

  • Se si compila questo esempio di codice in Visual Studio, è necessario modificare il nome della classe in modo che includa lo spazio dei nomi quando si passa la classe al metodo CreateInstanceAndUnwrap.If you build this code example in Visual Studio, you must change the name of the class to include the namespace when you pass it to the CreateInstanceAndUnwrap method. Per impostazione predefinita, lo spazio dei nomi è il nome del progetto.By default, the namespace is the name of the project. Ad esempio, se il progetto è "PartialTrust", il nome della classe deve essere "PartialTrust.Worker".For example, if the project is "PartialTrust", the class name must be "PartialTrust.Worker".

Vedi ancheSee also