Exemplarische Vorgehensweise: Ausgeben von Code in Szenarios mit teilweiser Vertrauenswürdigkeit

Aktualisiert: November 2007

Die Reflektionsausgabe verwendet für volle oder teilweise Vertrauenswürdigkeit den gleichen API-Satz, für teilweise vertrauenswürdigen Code erfordern einige Features allerdings besondere Berechtigungen. Außerdem verfügt die Reflektionsausgabe über ein Feature für anonym gehostete dynamische Methoden, das zur Verwendung mit teilweiser Vertrauenswürdigkeit und sicherheitstransparenten Assemblys vorgesehen ist.

Hinweis:

Vor .NET Framework Version 3.5 war zur Ausgabe von Code ReflectionPermission mit dem ReflectionPermissionFlag.ReflectionEmit-Flag erforderlich. Diese Berechtigung ist standardmäßig im benannten FullTrust-Berechtigungssatz und im Intranet-Berechtigungssatz enthalten, jedoch nicht im Internet-Berechtigungssatz. Daher konnte eine Bibliothek nur dann mit teilweiser Vertrauenswürdigkeit verwendet werden, wenn sie über das SecurityCriticalAttribute-Attribut verfügte und zudem eine Assert-Methode für ReflectionEmit ausführte. Diese Bibliotheken erfordern eine sorgfältige Sicherheitsüberprüfung, da Codierungsfehler zu Sicherheitslücken führen können. In .NET Framework 3.5 ist es möglich, Code in teilweise vertrauenswürdigen Szenarios ohne Sicherheitsanforderungen auszugeben, da das Generieren von Code an sich keinen privilegierten Vorgang darstellt. Das bedeutet, dass der generierte Code nicht mehr Berechtigungen aufweist als die Assembly, die ihn ausgibt. Bibliotheken, die Code ausgeben, können somit sicherheitstransparent sein und setzen keine ReflectionEmit-Assertion voraus, sodass zum Schreiben einer sicheren Bibliothek keine genaue Sicherheitsüberprüfung erforderlich ist.

In dieser exemplarischen Vorgehensweise werden die folgenden Aufgaben veranschaulicht:

  • Einrichten von teilweise vertrauenswürdigen Umgebungen zum Testen von Code

  • Ausführen von Code in teilweise vertrauenswürdigen Anwendungsdomänen

  • Verwenden von anonym gehosteten dynamischen Methoden zum Ausgeben und Ausführen von Code in Szenarios mit teilweiser Vertrauenswürdigkeit

Weitere Informationen zum Ausgeben von Code in Szenarios mit teilweiser Vertrauenswürdigkeit finden Sie unter Sicherheitsaspekte bei der Reflektionsausgabe.

Eine vollständige Auflistung des in diesen Verfahren dargestellten Codes finden Sie im Beispielabschnitt am Ende dieser exemplarischen Vorgehensweise.

Einrichten von teilweise vertrauenswürdigen Speicherorten

Die folgenden Verfahren enthalten Informationen zum Einrichten von Speicherorten, über die Code mit teilweiser Vertrauenswürdigkeit ausgeführt werden kann.

  • Im ersten Verfahren wird beschrieben, wie Sie eine Sandbox-Anwendungsdomäne erstellen, in der Code mit Internetvertrauenswürdigkeit ausgeführt wird. Darüber hinaus wird auf einen häufigen Fehler eingegangen.

  • Im zweiten Verfahren wird beschrieben, wie Sie der teilweise vertrauenswürdigen Anwendungsdomäne ReflectionPermission mit dem ReflectionPermissionFlag.RestrictedMemberAccess-Flag hinzufügen, um Zugriff auf private Daten in Assemblys mit gleicher oder geringerer Vertrauenswürdigkeit zu ermöglichen.

  • Im dritten Verfahren wird beschrieben, wie Sie eine Codegruppe erstellen, die einem Ordner eine Vertrauensebene zuordnet, sodass alle Assemblys in diesem Ordner mit teilweiser Vertrauenswürdigkeit ausgeführt werden.

Zusätzlich zu diesen Verfahren können Sie in einfachen Szenarios ein Assemblyattribut wie das folgende verwenden, um eine Assembly ohne SkipVerification-Berechtigung auszuführen. Auf eine ähnliche Weise können Sie ein Attribut verwenden, um die MemberAccess-Berechtigung zu verweigern.

<Assembly:SecurityPermissionAttribute(SecurityAction.RequestRefuse, Flags:=SecurityPermissionFlag.SkipVerification)>
[assembly:SecurityPermissionAttribute(SecurityAction.RequestRefuse, Flags=SecurityPermissionFlag.SkipVerification)]

Erstellen von Sandbox-Anwendungsdomänen

Um eine Anwendungsdomäne zu erstellen, in der Ihre Assemblys mit teilweiser Vertrauenswürdigkeit ausgeführt werden, müssen Sie den Satz der Berechtigungen, die den Assemblys erteilt werden sollen, mithilfe der AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, array<StrongName[])-Methodenüberladung angeben. Am einfachsten ist es, einen benannten Berechtigungssatz aus der Sicherheitsrichtlinie abzurufen.

Vorsicht:

Eine Sandbox-Anwendungsdomäne kann nicht allein durch Angabe eines Beweises erstellt werden. Sie müssen einen Berechtigungssatz oder eine Richtlinienebene für die Anwendungsdomäne angeben. (Das Einrichten einer Richtlinienebene für die Anwendungsdomäne wird in diesem Thema nicht beschrieben.) Wenn Sie beispielsweise die CreateDomain(String, Evidence)-Methodenüberladung mit dem Internetbeweis verwenden, werden die Berechtigungen nur an der Grenze der Anwendungsdomäne erzwungen. Innerhalb der Anwendungsdomäne werden den Assemblys Berechtigungen gemäß der Standardsicherheitsrichtlinie erteilt. Eine Konsolenanwendung auf dem Computer erhielte demnach volle Vertrauenswürdigkeit.

Im folgenden Verfahren wird eine Sandbox-Anwendungsdomäne erstellt, die Code mit teilweiser Vertrauenswürdigkeit ausführt, um Szenarios zu testen, in denen ausgegebener Code nur auf öffentliche Member öffentlicher Typen zugreifen kann. In einem späteren Verfahren wird beschrieben, wie Sie RestrictedMemberAccess hinzufügen, um Szenarios zu testen, in denen ausgegebener Code auf nicht öffentliche Typen und Member in Assemblys zugreifen kann, denen die gleichen oder geringere Berechtigungen erteilt wurden.

So erstellen Sie eine Anwendungsdomäne mit teilweiser Vertrauenswürdigkeit

  1. Verwenden Sie die folgende Hilfsfunktion, um benannte Berechtigungssätze aus der Sicherheitsrichtlinie abzurufen.

    Private Shared Function GetNamedPermissionSet(ByVal name As String) As PermissionSet 
    
        If (String.IsNullOrEmpty(name)) Then 
            Throw New ArgumentException("name", "Cannot search for a permission set without a name.")
        End If
    
        Dim foundName As Boolean = False
        Dim setIntersection As New PermissionSet(PermissionState.Unrestricted)
    
        ' Search all policy levels.
        Dim levelEnumerator As IEnumerator = SecurityManager.PolicyHierarchy()
        While (levelEnumerator.MoveNext())
    
            Dim level As PolicyLevel = levelEnumerator.Current 
            Debug.Assert(level IsNot Nothing)
    
            ' If this policy level has a named permission set with the 
            ' specified name, intersect it with previous levels.
            Dim levelSet As PermissionSet = level.GetNamedPermissionSet(name)
            If (levelSet IsNot Nothing) Then
    
                foundName = True
                setIntersection = setIntersection.Intersect(levelSet)
    
                ' Intersect() returns null for an empty set. If this occurs
                ' at any point, the resulting permission set is empty.
                If (setIntersection Is Nothing) Then
                    Return New PermissionSet(PermissionState.None)
                End If
            End If
        End While
    
        If Not foundName Then
            setIntersection = New PermissionSet(PermissionState.None)
        End If
        Return setIntersection
    
    End Function 
    
    private static PermissionSet GetNamedPermissionSet(string name)
    {
        if (String.IsNullOrEmpty(name))
            throw new ArgumentException("name", "Cannot search for a permission set without a name.");
    
        bool foundName = false;
        PermissionSet setIntersection = new PermissionSet(PermissionState.Unrestricted);
    
        // Search all policy levels.
        IEnumerator levelEnumerator = SecurityManager.PolicyHierarchy();
        while (levelEnumerator.MoveNext())
        {
            PolicyLevel level = levelEnumerator.Current as PolicyLevel;
            Debug.Assert(level != null);
    
            // If this policy level has a named permission set with the 
            // specified name, intersect it with previous levels.
            PermissionSet levelSet = level.GetNamedPermissionSet(name);
            if (levelSet != null)
            {
                foundName = true;
                setIntersection = setIntersection.Intersect(levelSet);
    
                // Intersect() returns null for an empty set. If this occurs
                // at any point, the resulting permission set is empty.
                if (setIntersection == null)
                    return new PermissionSet(PermissionState.None);
            }
        }
    
        if (!foundName)
            setIntersection = new PermissionSet(PermissionState.None);
    
        return setIntersection;
    }
    

    Ein Berechtigungssatz ist die Schnittmenge der auf allen Richtlinienebenen erteilten Berechtigungen. Eine bestimmte Berechtigung wird also erst erteilt, wenn sie auf allen Richtlinienebenen erteilt wurde. Daher beginnt die Hilfsfunktion mit einem Berechtigungssatz für volle Vertrauenswürdigkeit und listet die Ebenen der Richtlinienhierarchie auf, indem sie von der Schnittmenge dieses Berechtigungssatzes mit den für jede Ebene definierten Berechtigungen ausgeht.

    Hinweis:

    Mit der PermissionSet-Klasse können Sie Berechtigungssätze erstellen, die eine beliebige Kombination von Berechtigungen enthalten.

    Die Verwendung der Hilfsfunktion wird weiter unten in diesem Verfahren beschrieben.

  2. Erstellen Sie mithilfe von Sicherheitszonen einen Beweis für den teilweise vertrauenswürdigen Speicherort. In diesem Fall wird die Internetzone verwendet.

    Dim zoneEvidence() As Object = { New Zone(SecurityZone.Internet) }
    Dim internetZone As New Evidence(zoneEvidence, zoneEvidence)
    
    Object[] zoneEvidence = { new Zone(SecurityZone.Internet) };
    Evidence internetZone = new Evidence(zoneEvidence, zoneEvidence);
    
  3. Erstellen Sie ein AppDomainSetup-Objekt, um die Anwendungsdomäne mit einem Anwendungspfad zu initialisieren. In diesem Codebeispiel wird der aktuelle Ordner verwendet.

    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = "."
    
    AppDomainSetup adSetup = new AppDomainSetup();
    adSetup.ApplicationBase = ".";
    
  4. Verwenden Sie die Hilfsfunktion, um den benannten Berechtigungssatz aus der Systemrichtlinie abzurufen.

    Dim internetSet As PermissionSet = GetNamedPermissionSet("Internet")
    
    PermissionSet internetSet = GetNamedPermissionSet("Internet");
    
  5. Erstellen Sie die Anwendungsdomäne, indem Sie den Beweis, die Setupinformationen und den Berechtigungssatz angeben.

    Dim ad As AppDomain = AppDomain.CreateDomain("ChildDomain1", _
                                                 internetZone, _
                                                 adSetup, _
                                                 internetSet, _
                                                 Nothing)
    
    AppDomain ad = AppDomain.CreateDomain("ChildDomain1", 
                                          internetZone, 
                                          adSetup, 
                                          internetSet, 
                                          null);
    

    Mit dem letzten Parameter der AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, array<StrongName[])-Methodenüberladung können Sie anstelle des Berechtigungssatzes der Anwendungsdomäne eine Gruppe von Assemblys angeben, denen volle Vertrauenswürdigkeit erteilt werden soll. Die von der Anwendung verwendeten .NET Framework-Assemblys müssen Sie nicht angeben, da diese Assemblys im globalen Assemblycache enthalten sind. Assemblys im globalen Assemblycache sind immer voll vertrauenswürdig. Sie können diesen Parameter verwenden, um Assemblys mit starkem Namen anzugeben, die nicht im globalen Assemblycache enthalten sind.

Hinzufügen von eingeschränktem Memberzugriff auf Sandboxdomänen

Hostanwendungen können anonym gehosteten dynamischen Methoden Zugriff auf private Daten in Assemblys ermöglichen, die die gleiche oder eine geringere Vertrauensebene als die Assembly aufweisen, die den Code ausgibt. Um diese eingeschränkte Fähigkeit zum Überspringen von JIT-Sichtbarkeitsprüfungen zu ermöglichen, fügt die Hostanwendung dem Berechtigungssatz ein ReflectionPermission-Objekt mit dem ReflectionPermissionFlag.RestrictedMemberAccess-Flag hinzu.

Beispielsweise kann ein Host Internetanwendungen sowohl Internetberechtigungen als auch eingeschränkten Memberzugriff (RestrictedMemberAccess, RMA) erteilen, sodass eine Internetanwendung Code ausgeben kann, der auf private Daten in den eigenen Assemblys zugreift. Da der Zugriff auf Assemblys mit gleicher oder geringerer Vertrauenswürdigkeit beschränkt ist, kann eine Internetanwendung nicht auf Member voll vertrauenswürdiger Assemblys zugreifen, z. B. .NET Framework-Assemblys.

Hinweis:

Um Rechteerweiterungen zu verhindern, werden beim Erstellen anonym gehosteter dynamischer Methoden Stapelinformationen für die ausgebende Assembly einbezogen. Wenn die Methode aufgerufen wird, werden die Stapelinformationen überprüft. Daher ist eine anonym gehostete dynamische Methode, die über voll vertrauenswürdigen Code aufgerufen wird, auf die Vertrauensebene der ausgebenden Assembly beschränkt.

So erstellen Sie eine Anwendungsdomäne mit teilweiser Vertrauenswürdigkeit und eingeschränktem Memberzugriff

  1. Verwenden Sie die Hilfsfunktion, um den benannten Internet-Berechtigungssatz aus der Sicherheitsrichtlinie abzurufen.

    internetSet = GetNamedPermissionSet("Internet")
    
    internetSet = GetNamedPermissionSet("Internet");
    
  2. Erstellen Sie ein neues ReflectionPermission-Objekt mit dem RestrictedMemberAccess-Flag, und fügen Sie die Berechtigung mit der PermissionSet.SetPermission-Methode dem Berechtigungssatz hinzu.

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

    Wenn die Berechtigung noch nicht im Berechtigungssatz enthalten ist, wird sie mit der AddPermission-Methode hinzugefügt. Wenn die Berechtigung bereits im Berechtigungssatz enthalten ist, werden die angegebenen Flags der vorhandenen Berechtigung hinzugefügt.

    Hinweis:

    Das Feature des eingeschränkten Memberzugriffs ist ein Feature anonym gehosteter dynamischer Methoden. Wenn normale dynamische Methoden JIT-Sichtbarkeitsprüfungen überspringen, muss dem ausgegebenen Code ReflectionPermission mit dem ReflectionPermissionFlag.MemberAccess-Flag und dem RestrictedMemberAccess-Flag erteilt werden.

  3. Erstellen Sie die Anwendungsdomäne, indem Sie den Beweis, die Setupinformationen und den Berechtigungssatz angeben.

    ad = AppDomain.CreateDomain("ChildDomain2", _
                                internetZone, _
                                adSetup, _
                                internetSet, _
                                Nothing)
    
    ad = AppDomain.CreateDomain("ChildDomain2", 
                                internetZone, 
                                adSetup, 
                                internetSet, 
                                null);
    

Erstellen eines Ordners mit eingeschränkten Berechtigungen

Im folgenden Verfahren wird beschrieben, wie Sie eine Codegruppe erstellen, die einem Ordner Internetberechtigungen zuordnet, und wie Sie dem Berechtigungssatz für Code, der über den Ordner ausgeführt wird, das RestrictedMemberAccess-Flag hinzufügen.

So erstellen Sie einen Ordner mit Internetberechtigungen

  1. Klicken Sie auf Start, zeigen Sie auf Systemsteuerung, dann auf Verwaltung, und klicken Sie auf Microsoft .NET Framework 3.5-Konfiguration. Zur Verwendung des Konfigurationstools benötigen Sie Systemadministratorrechte.

  2. Erweitern Sie im linken Bereich unter .NET Framework 2.0-Konfiguration die Knoten Arbeitsplatz, Laufzeitsicherheitsrichtlinie, Computer, Codegruppen und All_Code.

  3. Klicken Sie im rechten Bereich auf Untergeordnete Codegruppe hinzufügen, um den Assistenten zum Erstellen einer Codegruppe auszuführen.

  4. Geben Sie für die Codegruppe einen Namen, z. B. "Internet Sandbox", und optional eine Beschreibung ein. Klicken Sie auf Weiter.

  5. Wählen Sie in der Liste Wählen Sie den Bedingungstyp für die Codegruppe aus den Eintrag URL aus. Geben Sie im Feld URL den vollständigen Pfad des gewünschten Ordners ein, und klicken Sie dann auf Weiter. Sie können z. B. Folgendes eingeben:

    file://c:/InternetSandbox/*
    
  6. Wählen Sie in der Liste Vorhandenen Berechtigungssatz verwenden den Eintrag Internet aus, und klicken Sie dann auf Weiter.

    Hinweis:

    Um einen benannten Berechtigungssatz und ein ReflectionPermission-Objekt mit dem RestrictedMemberAccess-Flag anzugeben, klicken Sie auf Neuen Berechtigungssatz erstellen und geben den benutzerdefinierten Berechtigungssatz mithilfe einer XML-Datei an.

  7. Klicken Sie auf Fertig stellen, um die Codegruppe zu erstellen.

  8. Platzieren Sie die Assemblys, die Sie mit eingeschränkter Vertrauenswürdigkeit ausführen möchten, in dem Ordner, den Sie in Schritt 5 angegeben haben.

Ausführen von Code in Sandbox-Anwendungsdomänen

Im folgenden Verfahren wird beschrieben, wie Sie eine Klasse mit Methoden definieren, die in einer Anwendungsdomäne ausgeführt werden können, wie Sie eine Instanz dieser Klasse in der Domäne erstellen und wie Sie deren Methoden ausführen.

So definieren Sie eine Methode in einer Anwendungsdomäne und führen sie aus

  1. Definieren Sie eine Klasse, die sich von MarshalByRefObject ableitet. Auf diese Weise können Sie Instanzen der Klasse in anderen Anwendungsdomänen erstellen und Methoden über die Grenzen der Anwendungsdomäne hinweg aufrufen. Die Klasse in diesem Beispiel hat den Namen Worker.

    Public Class Worker
        Inherits MarshalByRefObject
    
    public class Worker : MarshalByRefObject
    {
    
  2. Definieren Sie eine öffentliche Methode, die den Code enthält, den Sie ausführen möchten. In diesem Beispiel gibt der Code eine einfache dynamische Methode aus, erstellt einen Delegaten zum Ausführen der Methode und ruft den Delegaten auf.

    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
    
    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();
    }
    
  3. Rufen Sie im Hauptprogramm den Anzeigenamen der Assembly ab. Dieser Name wird verwendet, wenn Sie Instanzen der Worker-Klasse in der Sandbox-Anwendungsdomäne erstellen.

    Dim asmName As String = [Assembly].GetExecutingAssembly().FullName
    
    String asmName = Assembly.GetExecutingAssembly().FullName;
    
  4. Erstellen Sie im Hauptprogramm eine Sandbox-Anwendungsdomäne, wie im ersten Verfahren dieser exemplarischen Vorgehensweise beschrieben. Sie müssen dem Internet-Berechtigungssatz keine Berechtigungen hinzufügen, da die SimpleEmitDemo-Methode nur öffentliche Methoden verwendet.

  5. Erstellen Sie im Hauptprogramm eine Instanz der Worker-Klasse in der Sandbox-Anwendungsdomäne.

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

    Die CreateInstanceAndUnwrap-Methode erstellt das Objekt in der Zielanwendungsdomäne und gibt einen Proxy zurück, der zum Aufrufen der Eigenschaften und Methoden des Objekts verwendet werden kann.

    Hinweis:

    Wenn Sie diesen Code in Visual Studio verwenden, müssen Sie den Namespace in den Namen der Klasse einbeziehen. Standardmäßig ist der Namespace der Name des Projekts. Wenn das Projekt z. B. "PartialTrust" heißt, muss der Klassenname "PartialTrust.Worker" lauten.

  6. Fügen Sie Code zum Aufrufen der SimpleEmitDemo-Methode hinzu. Der Aufruf wird über die Grenze der Anwendungsdomäne hinweg gemarshallt, und der Code wird in der Sandbox-Anwendungsdomäne ausgeführt.

    w.SimpleEmitDemo()
    
    w.SimpleEmitDemo();
    

Verwenden von anonym gehosteten dynamischen Methoden

Anonym gehostete dynamische Methoden werden einer Assembly zugeordnet, die vom System bereitgestellt wird. Somit sind sie von anderem Code isoliert. Normale dynamische Methoden müssen hingegen einem vorhandenen Modul oder Typ zugeordnet werden.

Hinweis:

Die einzige Möglichkeit, der Assembly, die anonymes Hosting bereitstellt, eine dynamische Methode zuzuordnen, ist die Verwendung der in den folgenden Verfahren beschriebenen Konstruktoren. Es ist nicht möglich, ein Modul in der anonymen Hostingassembly explizit anzugeben.

Normale dynamische Methoden verfügen über Zugriff auf die internen Member des Moduls, dem sie zugeordnet sind, oder auf die privaten Member des Typs, dem sie zugeordnet sind. Da anonym gehostete dynamische Methoden von anderem Code isoliert sind, verfügen sie über keinen Zugriff auf private Daten. Sie besitzen jedoch die eingeschränkte Fähigkeit, JIT-Sichtbarkeitsprüfungen zu überspringen, um Zugriff auf private Daten zu erhalten. Diese Möglichkeit ist auf Assemblys beschränkt, die die gleiche oder eine geringere Vertrauensebene aufweisen als die Assembly, die den Code ausgibt.

Um Rechteerweiterungen zu verhindern, werden beim Erstellen anonym gehosteter dynamischer Methoden Stapelinformationen für die ausgebende Assembly einbezogen. Wenn die Methode aufgerufen wird, werden die Stapelinformationen überprüft. Eine anonym gehostete dynamische Methode, die über voll vertrauenswürdigen Code aufgerufen wird, ist auf die Vertrauensebene der ausgebenden Assembly beschränkt.

So verwenden Sie anonym gehostete dynamische Methoden

  • Erstellen Sie eine anonym gehostete dynamische Methode, indem Sie einen Konstruktor verwenden, der kein zugeordnetes Modul und keinen zugeordneten Typ angibt.

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

    Wenn eine anonym gehostete dynamische Methode nur öffentliche Typen und Methoden verwendet, erfordert sie keinen eingeschränkten Memberzugriff und muss keine JIT-Sichtbarkeitsprüfungen überspringen.

    Zur Ausgabe einer dynamischen Methode sind keine speziellen Berechtigungen erforderlich. Der ausgegebene Code erfordert jedoch die Berechtigungen, die von den verwendeten Typen und Methoden verlangt werden. Wenn der ausgegebene Code z. B. eine Methode aufruft, die auf eine Datei zugreift, erfordert er FileIOPermission. Wenn diese Berechtigung in der Vertrauensebene nicht enthalten ist, wird eine Sicherheitsausnahme ausgelöst, sobald der ausgegebene Code ausgeführt wird. Der hier dargestellte Code gibt eine dynamische Methode aus, die nur die Console.WriteLine-Methode verwendet. Daher kann der Code über teilweise vertrauenswürdige Speicherorte ausgeführt werden.

  • Alternativ können Sie eine anonym gehostete dynamische Methode mit eingeschränkter Fähigkeit zum Überspringen von JIT-Sichtbarkeitsprüfungen erstellen, indem Sie den DynamicMethod(String, Type, array<Type[], Boolean)-Konstruktor verwenden und true für den restrictedSkipVisibility-Parameter angeben.

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

    Die Einschränkung besteht darin, dass die anonym gehostete dynamische Methode nur auf private Daten in Assemblys zugreifen kann, die die gleiche oder eine geringere Vertrauensebene als die ausgebende Assembly aufweisen. Wenn die dynamische Methode z. B. mit Internetvertrauenswürdigkeit ausgeführt wird, kann sie auf private Daten in Assemblys zugreifen, die ebenfalls mit Internetvertrauenswürdigkeit ausgeführt werden, jedoch nicht auf private Daten in .NET Framework-Assemblys. .NET Framework-Assemblys werden im globalen Assemblycache installiert und sind immer voll vertrauenswürdig.

    Anonym gehostete dynamische Methoden können diese eingeschränkte Fähigkeit zum Überspringen von JIT-Sichtbarkeitsprüfungen nur verwenden, wenn die Hostanwendung ReflectionPermission mit dem ReflectionPermissionFlag.RestrictedMemberAccess-Flag erteilt. Diese Berechtigung wird angefordert, wenn die Methode aufgerufen wird.

    Hinweis:

    Beim Erstellen der dynamischen Methode werden Aufruflisteninformationen für die ausgebende Assembly einbezogen. Daher bezieht sich die Anforderung auf die Berechtigungen der ausgebenden Assembly und nicht der Assembly, die die Methode aufruft. Somit wird verhindert, dass der ausgegebene Code mit erweiterten Berechtigungen ausgeführt wird.

    Das vollständige Codebeispiel am Ende dieser exemplarischen Vorgehensweise veranschaulicht die Verwendung und die Einschränkungen des eingeschränkten Memberzugriffs. Die dort verwendete Worker-Klasse beinhaltet eine Methode, die anonym gehostete dynamische Methoden mit oder ohne eingeschränkte Fähigkeit zum Überspringen von Sichtbarkeitsprüfungen erstellen kann. Das Beispiel zeigt das Ergebnis der Ausführung dieser Methode in Anwendungsdomänen mit verschiedenen Vertrauensebenen.

    Hinweis:

    Die eingeschränkte Fähigkeit zum Überspringen von Sichtbarkeitsprüfungen ist ein Feature anonym gehosteter dynamischer Methoden. Wenn normale dynamische Methoden JIT-Sichtbarkeitsprüfungen überspringen, muss ihnen ReflectionPermission mit dem ReflectionPermissionFlag.MemberAccess-Flag erteilt werden. Zusätzlich muss normalen dynamischen Methoden, die auf private Daten in anderen Assemblys als der ausgebenden Assembly zugreifen, entweder ReflectionPermission mit dem RestrictedMemberAccess-Flag oder SecurityPermission mit dem SecurityPermissionFlag.ControlEvidence-Flag erteilt werden.

Beispiel

Beschreibung

Das folgende Codebeispiel veranschaulicht die Verwendung des RestrictedMemberAccess-Flags, um anonym gehosteten dynamischen Methoden das Überspringen von JIT-Sichtbarkeitsprüfungen zu ermöglichen, wenn der Zielmember die gleiche oder eine geringere Vertrauensebene aufweist als die Assembly, die den Code ausgibt.

Im Beispiel wird eine Worker-Klasse definiert, die über die Grenzen der Anwendungsdomäne hinweg gemarshallt werden kann. Die Klasse verfügt über zwei AccessPrivateMethod-Methodenüberladungen, die dynamische Methoden ausgeben und ausführen. Die erste Überladung gibt eine dynamische Methode (mit oder ohne JIT-Sichtbarkeitsprüfungen) aus, die die private PrivateMethod-Methode der Worker-Klasse aufruft. Die zweite Überladung gibt eine dynamische Methode aus, die auf eine internal-Eigenschaft (Friend-Eigenschaft in Visual Basic) der String-Klasse zugreift.

In dem Beispiel wird die Internet-Berechtigung mit einer Hilfsmethode aus der Sicherheitsrichtlinie abgerufen und anschließend eine Anwendungsdomäne erstellt, wobei mit der AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, array<StrongName[])-Methodenüberladung angegeben wird, dass der gesamte Code, der in der Domäne ausgeführt wird, diesen Berechtigungssatz verwendet. Außerdem wird eine Instanz der Worker-Klasse in der Anwendungsdomäne erstellt und die AccessPrivateMethod-Methode zweimal ausgeführt.

  • Bei der ersten Ausführung der AccessPrivateMethod-Methode werden JIT-Sichtbarkeitsprüfungen erzwungen. Die dynamische Methode schlägt fehl, wenn sie aufgerufen wird, da sie durch JIT-Sichtbarkeitsprüfungen daran gehindert wird, auf die private Methode zuzugreifen.

  • Bei der zweiten Ausführung der AccessPrivateMethod-Methode werden JIT-Sichtbarkeitsprüfungen übersprungen. Die dynamische Methode schlägt fehl, wenn sie kompiliert wird, da der Internet-Berechtigungssatz keine ausreichenden Berechtigungen zum Überspringen von Sichtbarkeitsprüfungen bereitstellt.

In dem Beispiel wird der Internet-Berechtigungssatz mit einer Hilfsmethode abgerufen und ReflectionPermission mit ReflectionPermissionFlag.RestrictedMemberAccess dem Berechtigungssatz hinzugefügt. Anschließend wird eine zweite Domäne erstellt, wobei dem gesamten Code, der in der Domäne ausgeführt wird, die Berechtigungen im neuen Berechtigungssatz erteilt werden. Zusätzlich wird eine Instanz der Worker-Klasse in der neuen Anwendungsdomäne erstellt, und es werden beide Überladungen der AccessPrivateMethod-Methode ausgeführt.

  • Die erste Überladung der AccessPrivateMethod-Methode wird ausgeführt, und JIT-Sichtbarkeitsprüfungen werden übersprungen. Die dynamische Methode wird erfolgreich kompiliert und ausgeführt, da die Assembly, die den Code ausgibt, mit der Assembly identisch ist, die die private Methode enthält. Daher sind die Vertrauensebenen gleich. Wenn die Anwendung, die die Worker-Klasse enthält, über mehrere Assemblys verfügen würde, wäre der gleiche Prozess für jede dieser Assemblys erfolgreich, da sie alle die gleiche Vertrauensebene aufweisen würden.

  • Die zweite Überladung der AccessPrivateMethod-Methode wird ausgeführt, und JIT-Sichtbarkeitsprüfungen werden erneut übersprungen. Dieses Mal schlägt die dynamische Methode fehl, wenn sie kompiliert wird, da sie versucht, auf die internal FirstChar-Eigenschaft der String-Klasse zuzugreifen. Die Assembly, die die String-Klasse enthält, ist voll vertrauenswürdig. Somit weist sie eine höhere Vertrauensebene auf als die Assembly, die den Code ausgibt.

Dieser Vergleich zeigt, wie teilweise vertrauenswürdiger Code durch ReflectionPermissionFlag.RestrictedMemberAccess Sichtbarkeitsprüfungen für anderen teilweise vertrauenswürdigen Code überspringen kann, ohne die Sicherheit von vertrauenswürdigem Code zu gefährden.

Code

Imports System
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 = [Assembly].GetExecutingAssembly().FullName

        ' Create evidence for a partially trusted location and a setup object
        ' that specifies the current directory for the application directory.
        Dim zoneEvidence() As Object = { New Zone(SecurityZone.Internet) }
        Dim internetZone As New Evidence(zoneEvidence, zoneEvidence)
        Dim adSetup As New AppDomainSetup()
        adSetup.ApplicationBase = "."

        ' Retrieve the Internet grant set from system policy, and create 
        ' an application domain in which all code that executes is granted
        ' the permissions of an application run from the Internet.
        Dim internetSet As PermissionSet = GetNamedPermissionSet("Internet")
        Dim ad As AppDomain = AppDomain.CreateDomain("ChildDomain1", _
                                                     internetZone, _
                                                     adSetup, _
                                                     internetSet, _
                                                     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. Now create a grant set composed 
        ' of the permissions granted to an Internet application plus
        ' RestrictedMemberAccess, 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)
        internetSet = GetNamedPermissionSet("Internet")
        internetSet.SetPermission( _
            New ReflectionPermission( _
                ReflectionPermissionFlag.RestrictedMemberAccess))
        ad = AppDomain.CreateDomain("ChildDomain2", _
                                    internetZone, _
                                    adSetup, _
                                    internetSet, _
                                    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 


    ' This method retrieves a named permission set from security policy.
    ' The return value is the intersection of all permission sets with the
    ' given name, from all policy levels, or an empty permission set if the
    ' name is not found.
    Private Shared Function GetNamedPermissionSet(ByVal name As String) As PermissionSet 

        If (String.IsNullOrEmpty(name)) Then 
            Throw New ArgumentException("name", "Cannot search for a permission set without a name.")
        End If

        Dim foundName As Boolean = False
        Dim setIntersection As New PermissionSet(PermissionState.Unrestricted)

        ' Search all policy levels.
        Dim levelEnumerator As IEnumerator = SecurityManager.PolicyHierarchy()
        While (levelEnumerator.MoveNext())

            Dim level As PolicyLevel = levelEnumerator.Current 
            Debug.Assert(level IsNot Nothing)

            ' If this policy level has a named permission set with the 
            ' specified name, intersect it with previous levels.
            Dim levelSet As PermissionSet = level.GetNamedPermissionSet(name)
            If (levelSet IsNot Nothing) Then

                foundName = True
                setIntersection = setIntersection.Intersect(levelSet)

                ' Intersect() returns null for an empty set. If this occurs
                ' at any point, the resulting permission set is empty.
                If (setIntersection Is Nothing) Then
                    Return New PermissionSet(PermissionState.None)
                End If
            End If
        End While

        If Not foundName Then
            setIntersection = New PermissionSet(PermissionState.None)
        End If
        Return setIntersection

    End Function 

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 compiled.
'Worker.PrivateMethod()
'MethodAccessException was thrown when the delegate was compiled.
' 
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 = Assembly.GetExecutingAssembly().FullName;

        // Create evidence for a partially trusted location and a setup object
        // that specifies the current directory for the application directory.
        Object[] zoneEvidence = { new Zone(SecurityZone.Internet) };
        Evidence internetZone = new Evidence(zoneEvidence, zoneEvidence);
        AppDomainSetup adSetup = new AppDomainSetup();
        adSetup.ApplicationBase = ".";

        // Retrieve the Internet grant set from system policy, and create 
        // an application domain in which all code that executes is granted
        // the permissions of an application run from the Internet.
        PermissionSet internetSet = GetNamedPermissionSet("Internet");
        AppDomain ad = AppDomain.CreateDomain("ChildDomain1", 
                                              internetZone, 
                                              adSetup, 
                                              internetSet, 
                                              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 compiled.
        w.AccessPrivateMethod(true);


        // Unload the application domain. Now create a grant set composed 
        // of the permissions granted to an Internet application plus
        // RestrictedMemberAccess, 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);
        internetSet = GetNamedPermissionSet("Internet");
        internetSet.SetPermission(
            new ReflectionPermission(
                ReflectionPermissionFlag.RestrictedMemberAccess));
        ad = AppDomain.CreateDomain("ChildDomain2", 
                                    internetZone, 
                                    adSetup, 
                                    internetSet, 
                                    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 method retrieves a named permission set from security policy.
    // The return value is the intersection of all permission sets with the
    // given name, from all policy levels, or an empty permission set if the
    // name is not found.
    private static PermissionSet GetNamedPermissionSet(string name)
    {
        if (String.IsNullOrEmpty(name))
            throw new ArgumentException("name", "Cannot search for a permission set without a name.");

        bool foundName = false;
        PermissionSet setIntersection = new PermissionSet(PermissionState.Unrestricted);

        // Search all policy levels.
        IEnumerator levelEnumerator = SecurityManager.PolicyHierarchy();
        while (levelEnumerator.MoveNext())
        {
            PolicyLevel level = levelEnumerator.Current as PolicyLevel;
            Debug.Assert(level != null);

            // If this policy level has a named permission set with the 
            // specified name, intersect it with previous levels.
            PermissionSet levelSet = level.GetNamedPermissionSet(name);
            if (levelSet != null)
            {
                foundName = true;
                setIntersection = setIntersection.Intersect(levelSet);

                // Intersect() returns null for an empty set. If this occurs
                // at any point, the resulting permission set is empty.
                if (setIntersection == null)
                    return new PermissionSet(PermissionState.None);
            }
        }

        if (!foundName)
            setIntersection = new PermissionSet(PermissionState.None);

        return setIntersection;
    }
}

/* This code example produces the following output:

Hello, World!
MethodAccessException was thrown when the delegate was invoked.
MethodAccessException was thrown when the delegate was compiled.
Worker.PrivateMethod()
MethodAccessException was thrown when the delegate was compiled.
 */

Kompilieren des Codes

  • Wenn Sie dieses Codebeispiel in Visual Studio verwenden, müssen Sie den Namespace in den Namen der Klasse einbeziehen, wenn Sie sie an die CreateInstanceAndUnwrap-Methode übergeben. Standardmäßig ist der Namespace der Name des Projekts. Wenn das Projekt z. B. "PartialTrust" heißt, muss der Klassenname "PartialTrust.Worker" lauten.

Siehe auch

Aufgaben

Gewusst wie: Ausführen von teilweise vertrauenswürdigem Code in einer Sandbox

Konzepte

Sicherheitsaspekte bei der Reflektionsausgabe