Megosztás a következőn keresztül:


Útmutató: Kódkibocsátó kód részleges megbízhatósági forgatókönyvekben

A reflection emit ugyanazt az API-készletet használja teljes vagy részleges megbízhatóság esetén, de egyes funkciók speciális engedélyeket igényelnek a részben megbízható kódban. Emellett a tükröződés-emitt egy olyan funkcióval is rendelkezik, amely névtelenül üzemeltetett dinamikus metódusokat tartalmaz, amelyeket részleges megbízhatósággal és biztonságilag transzparens szerelvényekkel való használatra terveztek.

Megjegyzés

A 3.5-ös .NET-keretrendszer előtt a jelzővel együtt kell ReflectionPermission kibocsátania a ReflectionPermissionFlag.ReflectionEmit kódot. Ez az engedély alapértelmezés szerint szerepel a és Intranet a FullTrust nevesített engedélykészletekben, de az Internet engedélykészletben nem. Ezért a kódtár csak akkor használható részleges megbízhatósági kapcsolatból, ha rendelkezik az SecurityCriticalAttribute attribútummal, és egy metódust Assert is végrehajtott a számára ReflectionEmit. Az ilyen kódtárak gondos biztonsági felülvizsgálatot igényelnek, mert a kódolási hibák biztonsági réseket okozhatnak. A .NET-keretrendszer 3.5 lehetővé teszi, hogy a kód részleges megbízhatósági forgatókönyvekben biztonsági követelmények nélkül legyen kibocsátva, mivel a kód generálása nem eredendően kiemelt művelet. Ez azt jelzi, hogy a létrehozott kódnak nincs több engedélye, mint az azt kibocsátó szerelvénynek. Ez lehetővé teszi, hogy a kódot kibocsátó kódtárak biztonsági-transzparensek legyenek, és szükségtelenné teszik a megkövetelést ReflectionEmit, így a biztonságos kódtárak írása nem igényel ilyen alapos biztonsági felülvizsgálatot.

Ez az útmutató a következő feladatokat mutatja be:

A kód részleges megbízhatósági forgatókönyvekben való kibocsátásával kapcsolatos további információkért lásd: Biztonsági problémák a tükröződés kibocsátásában.

Az eljárásokban látható kód teljes felsorolásáért tekintse meg az útmutató végén található Példa szakaszt .

Részben megbízható helyek beállítása

Az alábbi két eljárás bemutatja, hogyan állíthat be olyan helyeket, ahonnan részleges megbízhatósággal tesztelheti a kódot.

  • Az első eljárás bemutatja, hogyan hozhat létre egy védőfalas alkalmazástartományt, amelyben a kód internetes engedélyeket kap.

  • A második eljárás bemutatja, hogyan adhatja hozzá ReflectionPermission a ReflectionPermissionFlag.RestrictedMemberAccess jelzőt egy részben megbízható alkalmazástartományhoz, hogy lehetővé tegye a privát adatokhoz való hozzáférést egyenlő vagy kisebb megbízhatóságú szerelvényekben.

Védőfalas alkalmazástartományok létrehozása

Ha olyan alkalmazástartományt szeretne létrehozni, amelyben a szerelvények részleges megbízhatósággal futnak, meg kell adnia a szerelvények számára az alkalmazástartomány létrehozásához a metódustúlterheltség használatával AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) adható engedélyeket. A támogatási készlet megadásának legegyszerűbb módja egy elnevezett engedélykészlet lekérése a biztonsági szabályzatból.

Az alábbi eljárás egy tesztkörnyezeti alkalmazástartományt hoz létre, amely részleges megbízhatósággal futtatja a kódot, és teszteli azokat a forgatókönyveket, amelyekben a kibocsátott kód csak nyilvános típusú nyilvános tagokhoz fér hozzá. Egy későbbi eljárás bemutatja, hogyan adhat hozzá RestrictedMemberAccess, és tesztelheti azokat a forgatókönyveket, amelyekben a kibocsátott kód hozzáférhet a nem nyilvános típusokhoz és tagokhoz olyan szerelvényekben, amelyek egyenlő vagy kisebb engedélyekkel rendelkeznek.

Részleges megbízhatóságú alkalmazástartomány létrehozása

  1. Hozzon létre egy engedélykészletet a tesztkörnyezeti alkalmazástartományban lévő szerelvények számára. Ebben az esetben az internetzóna engedélykészletét használja a rendszer.

    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. Hozzon létre egy AppDomainSetup objektumot, amellyel inicializálhatja az alkalmazástartományt egy alkalmazáselérési úttal.

    Fontos

    Az egyszerűség kedvéért ez a példakód az aktuális mappát használja. Az internetről származó kód futtatásához használjon egy külön mappát a nem megbízható kódhoz, az Útmutató: Részben megbízható kód futtatása tesztkörnyezetben című témakörben leírtak szerint.

    AppDomainSetup adSetup = new AppDomainSetup();
    adSetup.ApplicationBase = ".";
    
    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = "."
    
  3. Hozza létre az alkalmazástartományt, és adja meg az alkalmazástartomány beállítási adatait és az alkalmazástartományban végrehajtott összes szerelvény engedélyezési készletét.

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

    A metódus túlterhelésének utolsó paramétere AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) lehetővé teszi olyan szerelvények megadását, amelyek teljes megbízhatóságot kapnak az alkalmazástartomány engedélyezési készlete helyett. Nem kell megadnia az alkalmazás által használt .NET-keretrendszer szerelvényeket, mert ezek a szerelvények a globális szerelvény-gyorsítótárban találhatók. A globális szerelvény-gyorsítótárban lévő szerelvények mindig teljes mértékben megbízhatók. Ez a paraméter olyan erős nevű szerelvények megadására használható, amelyek nem szerepelnek a globális szerelvény-gyorsítótárban.

RestrictedMemberAccess hozzáadása védőfalas tartományokhoz

A gazdagépalkalmazások lehetővé tehetik, hogy a névtelenül üzemeltetett dinamikus metódusok hozzáférjenek a kódot kibocsátó szerelvény megbízhatósági szintjénél vagy annál kisebb megbízhatósági szinttel rendelkező szerelvényekben lévő privát adatokhoz. Annak érdekében, hogy ez a korlátozott képesség átugorhassa az igény szerinti (JIT) láthatósági ellenőrzéseket, a gazdaalkalmazás hozzáad egy ReflectionPermission objektumot az ReflectionPermissionFlag.RestrictedMemberAccess (RMA) jelzővel a támogatási készlethez.

Egy gazdagép például internetes engedélyeket adhat az internetes alkalmazásoknak, valamint az RMA-t, hogy egy internetes alkalmazás olyan kódot bocsátson ki, amely a saját szerelvényekben fér hozzá a privát adatokhoz. Mivel a hozzáférés egyenlő vagy kisebb megbízhatóságú szerelvényekre korlátozódik, az internetes alkalmazások nem férhetnek hozzá a teljes mértékben megbízható szerelvények, például .NET-keretrendszer szerelvények tagjaihoz.

Megjegyzés

A jogosultságszint-emelés megakadályozása érdekében a rendszer a névtelenül üzemeltetett dinamikus metódusok létrehozásakor a kibocsátó szerelvény veremadatait is tartalmazza. A metódus meghívásakor a rendszer ellenőrzi a veremadatokat. Így a teljesen megbízható kódból meghívott névtelenül üzemeltetett dinamikus metódusok továbbra is a kibocsátó szerelvény megbízhatósági szintjére korlátozódnak.

Részleges megbízhatósági kapcsolattal és RMA-val rendelkező alkalmazástartomány létrehozása

  1. Hozzon létre egy új ReflectionPermission objektumot az RestrictedMemberAccess (RMA) jelzővel, és a PermissionSet.SetPermission metódussal adja hozzá az engedélyt a támogatási csoporthoz.

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

    A AddPermission metódus hozzáadja az engedélyt az engedélykészlethez, ha még nem szerepel benne. Ha az engedély már szerepel a támogatási készletben, a megadott jelzők hozzá lesznek adva a meglévő engedélyhez.

    Megjegyzés

    Az RMA a névtelenül üzemeltetett dinamikus metódusok egyik funkciója. Ha a szokásos dinamikus metódusok kihagyják a JIT láthatósági ellenőrzését, a kibocsátott kód teljes megbízhatóságot igényel.

  2. Hozza létre az alkalmazástartományt, megadva az alkalmazástartomány beállítási adatait és a támogatási készletet.

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

Kód futtatása védőfalas alkalmazástartományokban

Az alábbi eljárás azt ismerteti, hogyan definiálhat osztályt egy alkalmazástartományban végrehajtható metódusok használatával, hogyan hozhat létre egy osztálypéldányt a tartományban, és hogyan hajthatja végre a metódusait.

Metódus definiálása és végrehajtása egy alkalmazástartományban

  1. Definiáljon egy osztályt, amely a(z) osztályból MarshalByRefObjectszármazik. Ez lehetővé teszi a osztály példányainak létrehozását más alkalmazástartományokban, és metódushívásokat kezdeményezhet az alkalmazás tartományhatárai között. A példában szereplő osztály neve Worker.

    public class Worker : MarshalByRefObject
    {
    
    Public Class Worker
        Inherits MarshalByRefObject
    
  2. Definiáljon egy nyilvános metódust, amely tartalmazza a végrehajtani kívánt kódot. Ebben a példában a kód egy egyszerű dinamikus metódust bocsát ki, létrehoz egy delegáltat a metódus végrehajtásához, és meghívja a delegáltat.

    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. A fő programban kérje le a szerelvény megjelenítendő nevét. Ez a név akkor használatos, ha létrehozza a Worker osztály példányait a védőfalas alkalmazástartományban.

    String asmName = typeof(Worker).Assembly.FullName;
    
    Dim asmName As String = GetType(Worker).Assembly.FullName
    
  4. A fő programban hozzon létre egy védőfalas alkalmazástartományt az útmutató első eljárásában leírtak szerint. Nem kell engedélyeket hozzáadnia az Internet engedélykészlethez, mert a SimpleEmitDemo metódus csak nyilvános metódusokat használ.

  5. A fő programban hozza létre a Worker osztály egy példányát a védőfalas alkalmazástartományban.

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

    A CreateInstanceAndUnwrap metódus létrehozza az objektumot a célalkalmazás tartományában, és visszaad egy proxyt, amely az objektum tulajdonságainak és metódusainak meghívására használható.

    Megjegyzés

    Ha ezt a kódot használja a Visual Studióban, módosítania kell az osztály nevét, hogy tartalmazza a névteret. Alapértelmezés szerint a névtér a projekt neve. Ha például a projekt "PartialTrust", akkor az osztály nevének "PartialTrust.Worker" névnek kell lennie.

  6. Adjon hozzá kódot a metódus meghívásához SimpleEmitDemo . A hívás az alkalmazás tartományhatárán keresztül van rendezve, és a kód a védőfalas alkalmazástartományban lesz végrehajtva.

    w.SimpleEmitDemo();
    
    w.SimpleEmitDemo()
    

Névtelenül üzemeltetett dinamikus metódusok használata

A névtelenül üzemeltetett dinamikus metódusok a rendszer által biztosított transzparens szerelvényhez vannak társítva. Ezért az általuk tartalmazott kód átlátható. A szokásos dinamikus metódusokat viszont egy meglévő modulhoz kell társítani (akár közvetlenül meg vannak adva, akár egy társított típusból következtetnek rá), és biztonsági szintjüket az adott modulból kell elérni.

Megjegyzés

A dinamikus metódusok névtelen üzemeltetést biztosító szerelvényhez való társításának egyetlen módja az alábbi eljárásban leírt konstruktorok használata. A névtelen üzemeltetési szerelvényben nem adhat meg külön modult.

A szokásos dinamikus metódusok hozzáférhetnek a modul belső tagjaihoz, amelyekhez társítva vannak, vagy azokhoz a privát tagokhoz, amelyekhez társítva vannak. Mivel a névtelenül üzemeltetett dinamikus metódusok el vannak különítve a többi kódtól, nem férnek hozzá a privát adatokhoz. Azonban korlátozottan képesek átugorni a JIT láthatósági ellenőrzését a privát adatokhoz való hozzáféréshez. Ez a képesség olyan szerelvényekre korlátozódik, amelyek megbízhatósági szintje megegyezik vagy kisebb, mint a kódot kibocsátó szerelvény megbízhatósági szintje.

A jogosultságszint-emelés megakadályozása érdekében a rendszer a névtelenül üzemeltetett dinamikus metódusok létrehozásakor a kibocsátó szerelvény veremadatait is tartalmazza. A metódus meghívásakor a rendszer ellenőrzi a veremadatokat. A teljesen megbízható kódból meghívott névtelenül üzemeltetett dinamikus metódusok továbbra is az azt kibocsátó szerelvény megbízhatósági szintjére korlátozódnak.

Névtelenül üzemeltetett dinamikus metódusok használata

  • Névtelenül üzemeltetett dinamikus metódus létrehozása olyan konstruktor használatával, amely nem ad meg társított modult vagy típust.

    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)
    

    Ha egy névtelenül üzemeltetett dinamikus módszer csak nyilvános típusokat és metódusokat használ, nem igényel korlátozott taghozzáférést, és nem kell kihagynia a JIT láthatósági ellenőrzését.

    A dinamikus metódusok kibocsátásához nincs szükség különleges engedélyekre, de a kibocsátott kódhoz az általa használt típusok és metódusok által megkövetelt engedélyek szükségesek. Ha például a kibocsátott kód egy olyan metódust hív meg, amely hozzáfér egy fájlhoz, akkor a metódusnak szüksége van FileIOPermissionrá. Ha a megbízhatósági szint nem tartalmazza ezt az engedélyt, a rendszer biztonsági kivételt ad ki a kibocsátott kód végrehajtásakor. Az itt látható kód egy dinamikus metódust bocsát ki, amely csak a metódust Console.WriteLine használja. Ezért a kód részben megbízható helyekről is végrehajtható.

  • Másik lehetőségként hozzon létre egy névtelenül üzemeltetett dinamikus módszert, amelynek korlátozott lehetősége van a JIT láthatósági ellenőrzésének kihagyására a DynamicMethod(String, Type, Type[], Boolean) konstruktor használatával, és adja meg true a restrictedSkipVisibility paramétert.

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

    A korlátozás az, hogy a névtelenül üzemeltetett dinamikus módszer csak olyan szerelvényekben fér hozzá a privát adatokhoz, amelyek megbízhatósági szintje megegyezik a kibocsátó szerelvény megbízhatósági szintjével. Ha például a dinamikus módszer internetes megbízhatósági kapcsolattal hajtja végre a végrehajtást, akkor más, internetes megbízhatósággal is végrehajtható szerelvényekben is hozzáférhet a privát adatokhoz, de nem fér hozzá .NET-keretrendszer szerelvények privát adataihoz. .NET-keretrendszer szerelvények a globális szerelvény-gyorsítótárban vannak telepítve, és mindig teljes mértékben megbízhatóak.

    A névtelenül üzemeltetett dinamikus metódusok ezt a korlátozott képességet csak akkor hagyhatják ki a JIT láthatósági ellenőrzéseiből, ha a gazdaalkalmazás engedélyezi ReflectionPermission a ReflectionPermissionFlag.RestrictedMemberAccess jelző használatát. Ennek az engedélynek a kérése a metódus meghívásakor történik.

    Megjegyzés

    A rendszer a dinamikus metódus létrehozásakor tartalmazza a kibocsátó szerelvény hívási veremadatait. Ezért a rendszer a metódust meghívó szerelvény helyett a kibocsátó szerelvény engedélyeit követeli meg. Ez megakadályozza, hogy a kibocsátott kód emelt szintű engedélyekkel legyen végrehajtva.

    Az útmutató végén található teljes kód példája bemutatja a korlátozott taghozzáférés használatát és korlátozásait. Osztálya Worker tartalmaz egy metódust, amely névtelenül üzemeltetett dinamikus metódusokat hozhat létre a láthatósági ellenőrzések kihagyásának korlátozásával vagy anélkül, és a példa a metódus különböző megbízhatósági szinttel rendelkező alkalmazástartományokban való végrehajtásának eredményét mutatja be.

    Megjegyzés

    A láthatósági ellenőrzések kihagyásának korlátozása a névtelenül üzemeltetett dinamikus módszerek egyik funkciója. Ha a szokásos dinamikus metódusok kihagyják a JIT láthatósági ellenőrzését, teljes megbízhatóságot kell biztosítani számukra.

Példa

Leírás

Az alábbi példakód azt mutatja be, hogy a jelölő használatával lehetővé teszi a RestrictedMemberAccess névtelenül üzemeltetett dinamikus metódusok számára a JIT láthatósági ellenőrzésének kihagyását, de csak akkor, ha a céltag a kódot kibocsátó szerelvénynél egyenlő vagy alacsonyabb szintű megbízhatósági szinten van.

A példa egy olyan osztályt Worker határoz meg, amely az alkalmazás tartományhatárai között rendezhető el. Az osztály két AccessPrivateMethod metódust terhel, amelyek dinamikus metódusokat bocsátanak ki és hajtanak végre. Az első túlterhelés egy dinamikus metódust bocsát ki, amely meghívja az Worker osztály privát PrivateMethod metódusát, és jit láthatósági ellenőrzésekkel vagy anélkül is kibocsáthatja a dinamikus metódust. A második túlterhelés egy dinamikus metódust bocsát ki, amely hozzáfér az String osztály egy internal tulajdonságához (Frienda Visual Basic tulajdonságához).

A példa egy segédmetódussal hoz létre egy engedélyekre Internet korlátozott engedélyezési csoportot, majd létrehoz egy alkalmazástartományt a AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) metódus túlterhelésével annak megadásához, hogy a tartományban végrehajtott összes kód ezt az engedélyezési készletet használja. A példa létrehozza az osztály egy példányát az Worker alkalmazástartományban, és kétszer hajtja végre a AccessPrivateMethod metódust.

  • A metódus első végrehajtásakor a AccessPrivateMethod JIT láthatósági ellenőrzései kényszerítve lesznek. A dinamikus metódus meghívása meghiúsul, mert a JIT láthatósági ellenőrzései megakadályozzák, hogy hozzáférjen a privát metódushoz.

  • A metódus második végrehajtásakor a AccessPrivateMethod JIT láthatósági ellenőrzései kimaradnak. A dinamikus metódus fordításkor meghiúsul, mert a Internet támogatási csoport nem ad megfelelő engedélyeket a láthatósági ellenőrzések kihagyásához.

A példa a következővel ReflectionPermissionFlag.RestrictedMemberAccess egészíti ReflectionPermission ki a támogatási készletet. A példa ezután létrehoz egy második tartományt, amely megadja, hogy a tartományban végrehajtott összes kód megkapja az engedélyeket az új támogatási készletben. A példa létrehozza az osztály egy példányát az Worker új alkalmazástartományban, és végrehajtja a AccessPrivateMethod metódus mindkét túlterhelését.

  • A rendszer végrehajtja a metódus első túlterhelését, és kihagyja a AccessPrivateMethod JIT láthatósági ellenőrzését. A dinamikus metódus sikeresen lefordítja és végrehajtja, mert a kódot kibocsátó szerelvény megegyezik a privát metódust tartalmazó szerelvényrel. Ezért a megbízhatósági szintek egyenlőek. Ha az Worker osztályt tartalmazó alkalmazásnak több szerelvénye is van, ugyanez a folyamat bármelyik szerelvény esetében sikeres lenne, mert mindegyik azonos megbízhatósági szinten lenne.

  • A rendszer végrehajtja a AccessPrivateMethod metódus második túlterhelését, és ismét kihagyja a JIT láthatósági ellenőrzését. A dinamikus metódus fordítása ezúttal meghiúsul, mert megpróbálja elérni az internalFirstCharString osztály tulajdonságát. Az osztályt String tartalmazó szerelvény teljes mértékben megbízható. Ezért magasabb szintű megbízhatósági szinten van, mint a kódot kibocsátó szerelvény.

Ez az összehasonlítás azt mutatja be, hogyan ReflectionPermissionFlag.RestrictedMemberAccess teszi lehetővé a részben megbízható kód számára, hogy kihagyja a más részlegesen megbízható kód láthatósági ellenőrzését anélkül, hogy veszélyeztetné a megbízható kód biztonságát.

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

A kód fordítása

  • Ha ezt a kód példáját a Visual Studióban hozza létre, módosítania kell az osztály nevét úgy, hogy az tartalmazza a névteret, amikor átadja a CreateInstanceAndUnwrap metódusnak. Alapértelmezés szerint a névtér a projekt neve. Ha például a projekt "PartialTrust", akkor az osztálynévnek "PartialTrust.Worker"-nak kell lennie.

Lásd még