Delen via


Walkthrough: Code verzenden in scenario's met gedeeltelijke vertrouwensrelatie

Reflectie verzenden maakt gebruik van dezelfde API-set in volledig of gedeeltelijk vertrouwen, maar voor sommige functies zijn speciale machtigingen vereist in gedeeltelijk vertrouwde code. Bovendien heeft reflectie-emit een functie, anoniem gehoste dynamische methoden, die is ontworpen om te worden gebruikt met gedeeltelijk vertrouwen en door beveiligingstransparante assembly's.

Notitie

Voordat .NET Framework 3.5, moet u code verzenden die is vereist ReflectionPermission met de ReflectionPermissionFlag.ReflectionEmit vlag. Deze machtiging is standaard opgenomen in de FullTrust en Intranet benoemde machtigingensets, maar niet in de Internet machtigingenset. Daarom kan een bibliotheek alleen worden gebruikt vanuit een gedeeltelijke vertrouwensrelatie als deze het SecurityCriticalAttribute kenmerk heeft en ook een Assert methode voor ReflectionEmitheeft uitgevoerd. Dergelijke bibliotheken vereisen een zorgvuldige beveiligingsbeoordeling omdat coderingsfouten kunnen leiden tot beveiligingsgaten. Met de .NET Framework 3.5 kan code worden verzonden in scenario's met gedeeltelijke vertrouwensrelaties zonder dat er beveiligingsvereisten worden gesteld, omdat het genereren van code inherent geen bevoegde bewerking is. Dat wil dus dat de gegenereerde code niet meer machtigingen heeft dan de assembly die deze verzendt. Hierdoor kunnen bibliotheken die code verzenden, beveiligingstransparant zijn en is het niet meer nodig om te bevestigen ReflectionEmit, zodat het schrijven van een beveiligde bibliotheek niet zo'n grondige beveiligingsbeoordeling vereist.

In dit scenario ziet u de volgende taken:

Zie Beveiligingsproblemen in Reflectie verzenden voor meer informatie over het verzenden van code in scenario's met gedeeltelijke vertrouwensrelaties.

Zie de sectie Voorbeeld aan het einde van deze procedure voor een volledig overzicht van de code die in deze procedures wordt weergegeven.

Gedeeltelijk vertrouwde locaties instellen

De volgende twee procedures laten zien hoe u locaties instelt van waaruit u code kunt testen met gedeeltelijke vertrouwensrelatie.

  • De eerste procedure laat zien hoe u een toepassingsdomein in de sandbox maakt waarin code internetmachtigingen krijgt.

  • De tweede procedure laat zien hoe u met de ReflectionPermissionFlag.RestrictedMemberAccess vlag toevoegt ReflectionPermission aan een gedeeltelijk vertrouwd toepassingsdomein, om toegang tot persoonlijke gegevens in assembly's met een gelijk of minder vertrouwen mogelijk te maken.

Toepassingsdomeinen in de sandbox maken

Als u een toepassingsdomein wilt maken waarin uw assembly's met gedeeltelijk vertrouwen worden uitgevoerd, moet u de set machtigingen opgeven die aan de assembly's moeten worden verleend door de AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) methode overload te gebruiken om het toepassingsdomein te maken. De eenvoudigste manier om de toekenningsset op te geven, is door een benoemde machtigingenset op te halen uit het beveiligingsbeleid.

Met de volgende procedure maakt u een toepassingsdomein in de sandbox waarmee uw code wordt uitgevoerd met gedeeltelijk vertrouwen, om scenario's te testen waarin verzonden code alleen toegang heeft tot openbare leden van openbare typen. Een volgende procedure laat zien hoe u toevoegt RestrictedMemberAccessom scenario's te testen waarin verzonden code toegang heeft tot niet-openbare typen en leden in assembly's die gelijke of minder machtigingen hebben.

Een toepassingsdomein met gedeeltelijke vertrouwensrelatie maken

  1. Maak een machtigingenset om toe te kennen aan de assembly's in het toepassingsdomein in de sandbox. In dit geval wordt de machtigingenset van de internetzone gebruikt.

    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. Maak een AppDomainSetup -object om het toepassingsdomein te initialiseren met een toepassingspad.

    Belangrijk

    Voor het gemak wordt in dit codevoorbeeld de huidige map gebruikt. Als u code wilt uitvoeren die daadwerkelijk afkomstig is van internet, gebruikt u een afzonderlijke map voor de niet-vertrouwde code, zoals beschreven in Procedure: Gedeeltelijk vertrouwde code uitvoeren in een sandbox.

    AppDomainSetup adSetup = new AppDomainSetup();
    adSetup.ApplicationBase = ".";
    
    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = "."
    
  3. Maak het toepassingsdomein, waarbij u de installatiegegevens van het toepassingsdomein en de toekenningsset opgeeft voor alle assembly's die in het toepassingsdomein worden uitgevoerd.

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

    Met de laatste parameter van de overbelasting van de AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) methode kunt u een set assembly's opgeven die volledig vertrouwen moeten krijgen, in plaats van de toekenningsset van het toepassingsdomein. U hoeft niet de .NET Framework assembly's op te geven die door uw toepassing worden gebruikt, omdat deze assembly's zich in de globale assembly-cache bevinden. Assembly's in de globale assemblycache worden altijd volledig vertrouwd. U kunt deze parameter gebruiken om assembly's met sterke namen op te geven die zich niet in de globale assemblycache bevinden.

RestrictedMemberAccess toevoegen aan domeinen in de sandbox

Hosttoepassingen kunnen anoniem gehoste dynamische methoden toegang geven tot persoonlijke gegevens in assembly's met vertrouwensniveaus die gelijk zijn aan of lager zijn dan het vertrouwensniveau van de assembly die de code verzendt. Als u deze beperkte mogelijkheid voor het overslaan van JIT-zichtbaarheidscontroles (Just-In-Time) wilt inschakelen, voegt de hosttoepassing een ReflectionPermission object met de ReflectionPermissionFlag.RestrictedMemberAccess vlag (RMA) toe aan de toekenningsset.

Een host kan bijvoorbeeld internettoepassingen internetmachtigingen plus RMA verlenen, zodat een internettoepassing code kan verzenden die toegang heeft tot persoonlijke gegevens in zijn eigen assembly's. Omdat de toegang is beperkt tot assembly's met een gelijk of minder vertrouwensrelatie, kan een internettoepassing geen toegang krijgen tot leden van volledig vertrouwde assembly's, zoals .NET Framework assembly's.

Notitie

Om onrechtmatige uitbreiding van toegangsrechten te voorkomen, wordt stack-informatie voor de verzendende assembly opgenomen wanneer anoniem gehoste dynamische methoden worden gemaakt. Wanneer de methode wordt aangeroepen, wordt de stack-informatie gecontroleerd. Een anoniem gehoste dynamische methode die wordt aangeroepen vanuit volledig vertrouwde code, is dus nog steeds beperkt tot het vertrouwensniveau van de verzendende assembly.

Een toepassingsdomein maken met gedeeltelijk vertrouwen plus RMA

  1. Maak een nieuw ReflectionPermission object met de RestrictedMemberAccess vlag (RMA) en gebruik de PermissionSet.SetPermission methode om de machtiging toe te voegen aan de toekenningsset.

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

    De AddPermission methode voegt de machtiging toe aan de toekenningsset als deze nog niet is opgenomen. Als de machtiging al is opgenomen in de toekenningsset, worden de opgegeven vlaggen toegevoegd aan de bestaande machtiging.

    Notitie

    RMA is een functie van anoniem gehoste dynamische methoden. Wanneer normale dynamische methoden JIT-zichtbaarheidscontroles overslaan, vereist de verzonden code volledig vertrouwen.

  2. Maak het toepassingsdomein en geef de installatiegegevens van het toepassingsdomein en de toekenningsset op.

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

Code uitvoeren in toepassingsdomeinen in sandbox

In de volgende procedure wordt uitgelegd hoe u een klasse definieert met behulp van methoden die kunnen worden uitgevoerd in een toepassingsdomein, hoe u een exemplaar van de klasse in het domein maakt en hoe u de bijbehorende methoden uitvoert.

Een methode definiëren en uitvoeren in een toepassingsdomein

  1. Definieer een klasse die is afgeleid van MarshalByRefObject. Hiermee kunt u exemplaren van de klasse maken in andere toepassingsdomeinen en methode-aanroepen maken over de grenzen van het toepassingsdomein. De klasse in dit voorbeeld heet Worker.

    public class Worker : MarshalByRefObject
    {
    
    Public Class Worker
        Inherits MarshalByRefObject
    
  2. Definieer een openbare methode die de code bevat die u wilt uitvoeren. In dit voorbeeld verzendt de code een eenvoudige dynamische methode, maakt een gemachtigde om de methode uit te voeren en roept de gemachtigde aan.

    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. Haal in het hoofdprogramma de weergavenaam van uw assembly op. Deze naam wordt gebruikt wanneer u exemplaren van de Worker klasse maakt in het toepassingsdomein in de sandbox.

    String asmName = typeof(Worker).Assembly.FullName;
    
    Dim asmName As String = GetType(Worker).Assembly.FullName
    
  4. Maak in uw hoofdprogramma een toepassingsdomein in de sandbox, zoals beschreven in de eerste procedure in dit scenario. U hoeft geen machtigingen toe te voegen aan de Internet machtigingenset, omdat de SimpleEmitDemo methode alleen openbare methoden gebruikt.

  5. Maak in uw hoofdprogramma een exemplaar van de Worker klasse in het toepassingsdomein in de sandbox.

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

    De CreateInstanceAndUnwrap methode maakt het -object in het domein van de doeltoepassing en retourneert een proxy die kan worden gebruikt om de eigenschappen en methoden van het object aan te roepen.

    Notitie

    Als u deze code in Visual Studio gebruikt, moet u de naam van de klasse wijzigen om de naamruimte op te nemen. De naamruimte is standaard de naam van het project. Als het project bijvoorbeeld 'PartialTrust' is, moet de klassenaam 'PartialTrust.Worker' zijn.

  6. Voeg code toe om de SimpleEmitDemo methode aan te roepen. De aanroep wordt verspreid over de grens van het toepassingsdomein en de code wordt uitgevoerd in het toepassingsdomein in de sandbox.

    w.SimpleEmitDemo();
    
    w.SimpleEmitDemo()
    

Anoniem gehoste dynamische methoden gebruiken

Anoniem gehoste dynamische methoden zijn gekoppeld aan een transparante assembly die wordt geleverd door het systeem. Daarom is de code die ze bevatten transparant. Normale dynamische methoden moeten daarentegen worden gekoppeld aan een bestaande module (rechtstreeks opgegeven of afgeleid van een gekoppeld type) en hun beveiligingsniveau van die module overnemen.

Notitie

De enige manier om een dynamische methode te koppelen aan de assembly die anonieme hosting biedt, is door de constructors te gebruiken die in de volgende procedure worden beschreven. U kunt geen module expliciet opgeven in de anonieme hostingassembly.

Gewone dynamische methoden hebben toegang tot de interne leden van de module waaraan ze zijn gekoppeld of tot de privéleden van het type waaraan ze zijn gekoppeld. Omdat anoniem gehoste dynamische methoden zijn geïsoleerd van andere code, hebben ze geen toegang tot persoonlijke gegevens. Ze hebben echter een beperkte mogelijkheid om JIT-zichtbaarheidscontroles over te slaan om toegang te krijgen tot persoonlijke gegevens. Deze mogelijkheid is beperkt tot assembly's met vertrouwensniveaus die gelijk zijn aan of kleiner zijn dan het vertrouwensniveau van de assembly die de code verzendt.

Om onrechtmatige uitbreiding van toegangsrechten te voorkomen, wordt stack-informatie voor de verzendende assembly opgenomen wanneer anoniem gehoste dynamische methoden worden gemaakt. Wanneer de methode wordt aangeroepen, wordt de stack-informatie gecontroleerd. Een anoniem gehoste dynamische methode die wordt aangeroepen vanuit volledig vertrouwde code is nog steeds beperkt tot het vertrouwensniveau van de assembly die deze heeft verzonden.

Anoniem gehoste dynamische methoden gebruiken

  • Maak een anoniem gehoste dynamische methode met behulp van een constructor die geen gekoppelde module of type opgeeft.

    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)
    

    Als een anoniem gehoste dynamische methode alleen openbare typen en methoden gebruikt, is er geen beperkte toegang voor leden vereist en hoeft JIT-zichtbaarheidscontroles niet te worden overgeslagen.

    Er zijn geen speciale machtigingen vereist om een dynamische methode te verzenden, maar de verzonden code vereist de machtigingen die worden vereist door de typen en methoden die worden gebruikt. Als de verzonden code bijvoorbeeld een methode aanroept die toegang heeft tot een bestand, is hiervoor vereist FileIOPermission. Als het vertrouwensniveau deze machtiging niet bevat, wordt er een beveiligingsuitzondering gegenereerd wanneer de verzonden code wordt uitgevoerd. De code die hier wordt weergegeven, verzendt een dynamische methode die alleen de Console.WriteLine methode gebruikt. Daarom kan de code worden uitgevoerd vanaf gedeeltelijk vertrouwde locaties.

  • U kunt ook een anoniem gehoste dynamische methode maken met beperkte mogelijkheid om JIT-zichtbaarheidscontroles over te slaan, door de DynamicMethod(String, Type, Type[], Boolean) constructor te gebruiken en op te true geven voor de 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)
    

    De beperking is dat de anoniem gehoste dynamische methode alleen toegang heeft tot persoonlijke gegevens in assembly's met vertrouwensniveaus die gelijk zijn aan of kleiner zijn dan het vertrouwensniveau van de verzendende assembly. Als de dynamische methode bijvoorbeeld wordt uitgevoerd met internetvertrouwen, heeft deze toegang tot privégegevens in andere assembly's die ook worden uitgevoerd met internetvertrouwen, maar geen toegang tot privégegevens van .NET Framework assembly's. .NET Framework assembly's worden geïnstalleerd in de globale assemblycache en worden altijd volledig vertrouwd.

    Anoniem gehoste dynamische methoden kunnen deze beperkte mogelijkheid gebruiken om JIT-zichtbaarheidscontroles alleen over te slaan als de hosttoepassing verleent ReflectionPermission met de ReflectionPermissionFlag.RestrictedMemberAccess vlag. De vraag naar deze machtiging wordt gemaakt wanneer de methode wordt aangeroepen.

    Notitie

    Informatie over de aanroepstack voor de verzendende assembly wordt opgenomen wanneer de dynamische methode wordt samengesteld. Daarom wordt de vraag gemaakt op basis van de machtigingen van de verzendende assembly in plaats van de assembly die de methode aanroept. Hiermee voorkomt u dat de verzonden code wordt uitgevoerd met verhoogde machtigingen.

    In het volledige codevoorbeeld aan het einde van dit scenario ziet u het gebruik en de beperkingen van beperkte toegang voor leden. De Worker klasse bevat een methode waarmee anoniem gehoste dynamische methoden kunnen worden gemaakt met of zonder de beperkte mogelijkheid om zichtbaarheidscontroles over te slaan. In het voorbeeld ziet u het resultaat van het uitvoeren van deze methode in toepassingsdomeinen met verschillende vertrouwensniveaus.

    Notitie

    De beperkte mogelijkheid om zichtbaarheidscontroles over te slaan, is een functie van anoniem gehoste dynamische methoden. Wanneer gewone dynamische methoden JIT-zichtbaarheidscontroles overslaan, moeten ze volledig vertrouwen krijgen.

Voorbeeld

Beschrijving

In het volgende codevoorbeeld ziet u het gebruik van de RestrictedMemberAccess vlag om anoniem gehoste dynamische methoden toe te staan om JIT-zichtbaarheidscontroles over te slaan, maar alleen wanneer het doellid een gelijk of lager vertrouwensniveau heeft dan de assembly die de code verzendt.

In het voorbeeld wordt een Worker klasse gedefinieerd die kan worden gegroepeerd over de grenzen van het toepassingsdomein. De klasse heeft twee AccessPrivateMethod methode overloads die dynamische methoden verzenden en uitvoeren. De eerste overbelasting verzendt een dynamische methode die de persoonlijke PrivateMethod methode van de Worker klasse aanroept en kan de dynamische methode met of zonder JIT-zichtbaarheidscontroles verzenden. De tweede overbelasting verzendt een dynamische methode die toegang heeft tot een internal eigenschap (Friend eigenschap in Visual Basic) van de String klasse.

In het voorbeeld wordt een helpermethode gebruikt om een toekenningsset te maken die beperkt is tot Internet machtigingen. Vervolgens wordt een toepassingsdomein gemaakt, waarbij de AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) methode overload wordt gebruikt om op te geven dat alle code die in het domein wordt uitgevoerd, gebruikmaakt van deze toekenningsset. In het voorbeeld wordt een exemplaar van de Worker klasse in het toepassingsdomein gemaakt en wordt de AccessPrivateMethod methode twee keer uitgevoerd.

  • De eerste keer dat de AccessPrivateMethod methode wordt uitgevoerd, worden JIT-zichtbaarheidscontroles afgedwongen. De dynamische methode mislukt wanneer deze wordt aangeroepen, omdat JIT-zichtbaarheidscontroles voorkomen dat deze toegang heeft tot de persoonlijke methode.

  • De tweede keer dat de AccessPrivateMethod methode wordt uitgevoerd, worden JIT-zichtbaarheidscontroles overgeslagen. De dynamische methode mislukt wanneer deze wordt gecompileerd, omdat de Internet toekenningsset onvoldoende machtigingen verleent om zichtbaarheidscontroles over te slaan.

In het voorbeeld wordt met ReflectionPermissionFlag.RestrictedMemberAccess toegevoegd ReflectionPermission aan de toekenningsset. In het voorbeeld wordt vervolgens een tweede domein gemaakt, waarin wordt aangegeven dat aan alle code die in het domein wordt uitgevoerd, de machtigingen in de nieuwe toekenningsset worden verleend. In het voorbeeld wordt een exemplaar van de Worker klasse in het nieuwe toepassingsdomein gemaakt en worden beide overbelastingen van de AccessPrivateMethod methode uitgevoerd.

  • De eerste overbelasting van de AccessPrivateMethod methode wordt uitgevoerd en JIT-zichtbaarheidscontroles worden overgeslagen. De dynamische methode wordt gecompileerd en uitgevoerd, omdat de assembly die de code verzendt, hetzelfde is als de assembly die de privémethode bevat. Daarom zijn de vertrouwensniveaus gelijk. Als de toepassing die de Worker klasse bevat meerdere assembly's had, zou hetzelfde proces slagen voor een van deze assembly's, omdat ze allemaal op hetzelfde vertrouwensniveau zouden zijn.

  • De tweede overbelasting van de AccessPrivateMethod methode wordt uitgevoerd en opnieuw worden JIT-zichtbaarheidscontroles overgeslagen. Deze keer mislukt de dynamische methode wanneer deze wordt gecompileerd, omdat wordt geprobeerd toegang te krijgen tot de internalFirstChar eigenschap van de String klasse. De assembly die de String klasse bevat, wordt volledig vertrouwd. Daarom is het op een hoger vertrouwensniveau dan de assembly die de code verzendt.

Deze vergelijking laat zien hoe ReflectionPermissionFlag.RestrictedMemberAccess gedeeltelijk vertrouwde code de zichtbaarheidscontroles voor andere gedeeltelijk vertrouwde code overslaat zonder de beveiliging van vertrouwde code in gevaar te brengen.

Code

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.
' 

De code compileren

  • Als u dit codevoorbeeld in Visual Studio bouwt, moet u de naam van de klasse wijzigen zodat deze de naamruimte bevat wanneer u deze doorgeeft aan de CreateInstanceAndUnwrap methode. Standaard is de naamruimte de naam van het project. Als het project bijvoorbeeld 'PartialTrust' is, moet de klassenaam 'PartialTrust.Worker' zijn.

Zie ook