Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Reflectie-emit maakt gebruik van dezelfde API-set in volledige of gedeeltelijke vertrouwensrelatie, maar sommige functies vereisen speciale machtigingen in gedeeltelijk vertrouwde code. Bovendien heeft reflectie-emit een functie, anoniem gehoste dynamische methoden, die is ontworpen voor gebruik met gedeeltelijke vertrouwensrelatie en door beveiligingstransparante assembly's.
Opmerking
Voordat .NET Framework 3.5, het genereren van code vereiste 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 onder een gedeeltelijke vertrouwensrelatie worden gebruikt als het het kenmerk SecurityCriticalAttribute had en ook een Assert-methode voor ReflectionEmit uitvoerde. Voor dergelijke bibliotheken is zorgvuldige beveiligingsbeoordeling vereist, omdat coderingsfouten kunnen leiden tot beveiligingsgaten. Met .NET Framework 3.5 kan code worden verzonden in gedeeltelijke vertrouwensscenario's zonder dat er beveiligingsvereisten worden gesteld, omdat het genereren van code niet inherent een bevoorrechte bewerking is. Dat wil gezegd, de gegenereerde code heeft niet meer machtigingen dan de assembly die deze verzendt. Hierdoor kunnen bibliotheken die code verzenden transparant zijn en de noodzaak om te bevestigen ReflectionEmit, verwijderen, zodat het schrijven van een beveiligde bibliotheek geen dergelijke grondige beveiligingsbeoordeling vereist.
Deze handleiding illustreert de volgende taken:
Een eenvoudige sandbox instellen voor het testen van gedeeltelijk vertrouwde code.
Belangrijk
Dit is een eenvoudige manier om te experimenteren met code in gedeeltelijke vertrouwensrelatie. Als u code wilt uitvoeren die afkomstig is van niet-vertrouwde locaties, raadpleegt u Procedure: Gedeeltelijk vertrouwde code uitvoeren in een sandbox.
Code uitvoeren in gedeeltelijk vertrouwde toepassingsdomeinen.
Zie Beveiligingsproblemen in Reflectie Emit voor meer informatie over het verzenden van code in gedeeltelijke vertrouwensscenario's.
Zie de sectie Voorbeeld aan het einde van deze procedure voor een volledige lijst van de code die in deze procedures wordt weergegeven.
Gedeeltelijk vertrouwde locaties instellen
In de volgende twee procedures ziet u hoe u locaties instelt waaruit u code kunt testen met gedeeltelijke vertrouwensrelatie.
De eerste procedure laat zien hoe u een sandbox-toepassingsdomein maakt waarin aan code internetmachtigingen worden verleend.
In de tweede procedure ziet u hoe ReflectionPermission u met de ReflectionPermissionFlag.RestrictedMemberAccess vlag toevoegt aan een gedeeltelijk vertrouwd toepassingsdomein, om toegang tot persoonlijke gegevens in assembly's van gelijke of minder vertrouwensrelaties mogelijk te maken.
Sandbox-toepassingsdomeinen 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 overload-variant van de AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) methode te gebruiken om het toepassingsdomein te creëren. De eenvoudigste manier om de toekenningsset op te geven, is door een benoemde machtigingsset op te halen uit het beveiligingsbeleid.
Met de volgende procedure maakt u een toepassingsdomein in de sandbox dat uw code uitvoert met gedeeltelijke vertrouwensrelatie, om scenario's te testen waarin gegenereerde code alleen toegang heeft tot openbare leden van openbare typen. In een volgende procedure wordt getoond hoe u RestrictedMemberAccess kunt toevoegen om scenario's te testen waarin gegenereerde code toegang heeft tot niet-openbare typen en leden in assembly's die gelijke of lagere machtigingen hebben.
Een toepassingsdomein maken met gedeeltelijke vertrouwensrelatie
Maak een machtigingenset die moet worden verleend aan de assembly's in het domein van de sandboxtoepassing. 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))Maak een AppDomainSetup object om het toepassingsdomein te initialiseren met een toepassingspad.
Belangrijk
Voor het gemak gebruikt dit codevoorbeeld de huidige map. 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 = "."Maak het toepassingsdomein, waarbij u de installatiegegevens van het toepassingsdomein en de toekenningsset opgeeft voor alle assembly's die worden uitgevoerd in het toepassingsdomein.
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 moeten worden vertrouwd, 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 assemblycache bevinden. Assembly's in de globale assemblycache worden altijd volledig vertrouwd. U kunt deze parameter gebruiken om sterk benoemde assembly's op te geven die zich niet in de globale assemblycache bevinden.
RestrictedMemberAccess toevoegen aan sandbox-domeinen
Hosttoepassingen kunnen anoniem gehoste dynamische methoden toestaan om toegang te krijgen tot persoonlijke gegevens in assembly's met vertrouwensniveaus die gelijk zijn aan of kleiner zijn dan het vertrouwensniveau van de assembly die de code verzendt. Als u deze beperkte mogelijkheid wilt inschakelen om just-in-time (JIT)-zichtbaarheidscontroles over te slaan, voegt de hosttoepassing een ReflectionPermission object toe met de ReflectionPermissionFlag.RestrictedMemberAccess vlag (RMA) aan de toekenningsset.
Een host kan bijvoorbeeld internettoepassingen internetmachtigingen plus RMA verlenen, zodat een internettoepassing code kan uitvoeren die toegang heeft tot privégegevens in zijn eigen assembly's. Omdat de toegang is beperkt tot assembly's van gelijke of minder vertrouwensrelatie, heeft een internettoepassing geen toegang tot leden van volledig vertrouwde assembly's zoals .NET Framework-assembly's.
Opmerking
Om uitbreiding van bevoegdheden te voorkomen, wordt stack-informatie voor de verzendende assembly opgenomen wanneer anoniem gehoste dynamische methoden worden samengesteld. Wanneer de methode wordt aangeroepen, wordt de stackinformatie gecontroleerd. Daarom is een anoniem gehoste dynamische methode die wordt aangeroepen vanuit volledig vertrouwde code, nog steeds beperkt tot het vertrouwensniveau van de verzendende assembly.
Een toepassingsdomein maken met gedeeltelijk vertrouwen plus RMA
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 autorisatie toe aan de verzameling van toekenningen als deze nog niet is opgenomen. Als de machtiging al is opgenomen in de toekenningsset, worden de opgegeven vlaggen toegevoegd aan de bestaande machtiging.
Opmerking
RMA is een functie van anoniem gehoste dynamische methoden. Wanneer gewone dynamische methoden JIT-zichtbaarheidscontroles overslaan, is volledig vertrouwen vereist voor de verzonden code.
Maak het toepassingsdomein, waarbij u de installatiegegevens van het toepassingsdomein en de toekenningsset opgeeft.
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)
Code uitvoeren in sandbox-toepassingsdomeinen
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 methoden ervan uitvoert.
Een methode definiëren en uitvoeren in een toepassingsdomein
Definieer een klasse die is afgeleid van MarshalByRefObject. Hiermee kunt u exemplaren van de klasse maken in andere toepassingsdomeinen en methode-aanroepen uitvoeren binnen de grenzen van het toepassingsdomein. De klasse in dit voorbeeld heeft de naam
Worker.public class Worker : MarshalByRefObject {Public Class Worker Inherits MarshalByRefObjectDefinieer 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 SubHaal in het hoofdprogramma de weergavenaam van uw assembly op. Deze naam wordt gebruikt wanneer u exemplaren van de
Workerklasse maakt in het domein van de sandboxtoepassing.String asmName = typeof(Worker).Assembly.FullName;Dim asmName As String = GetType(Worker).Assembly.FullNameMaak in uw hoofdprogramma een geschermd toepassingsdomein, zoals beschreven in de eerste procedure in deze handleiding. U hoeft geen machtigingen toe te voegen aan de
Internetmachtigingenset, omdat voor deSimpleEmitDemomethode alleen openbare methoden worden gebruikt.Maak in uw hoofdprogramma een exemplaar van de
Workerklasse in het domein van de sandboxtoepassing.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.
Opmerking
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.
Voeg code toe om de
SimpleEmitDemomethode aan te roepen. De aanroep wordt gemarshald over de grens van het toepassingsdomein en de code wordt uitgevoerd in het gesandboxte toepassingsdomein.w.SimpleEmitDemo();w.SimpleEmitDemo()
Anoniem gehoste dynamische methoden gebruiken
Anoniem gehoste dynamische methoden worden gekoppeld aan een transparante assembly die door het systeem wordt geleverd. Daarom is de code die ze bevatten transparant. Gewone 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.
Opmerking
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 aan de privéleden van het type waaraan ze zijn gekoppeld. Omdat anoniem gehoste dynamische methoden worden 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 waarmee de code wordt verzonden.
Om uitbreiding van bevoegdheden te voorkomen, wordt stack-informatie voor de verzendende assembly opgenomen wanneer anoniem gehoste dynamische methoden worden samengesteld. Wanneer de methode wordt aangeroepen, wordt de stackinformatie 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 tot leden vereist en hoeft u geen JIT-zichtbaarheidscontroles over te slaan.
Er zijn geen speciale machtigingen vereist voor het verzenden van een dynamische methode, maar voor de verzonden code zijn de machtigingen vereist 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 dit 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 gebruikmaakt van de Console.WriteLine methode. 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 met behulp van de DynamicMethod(String, Type, Type[], Boolean) constructor en opgeven
truevoor derestrictedSkipVisibilityparameter.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 een internetvertrouwensrelatie, heeft deze toegang tot persoonlijke gegevens in andere assembly's die ook worden uitgevoerd met een internetvertrouwensrelatie, maar heeft deze geen toegang tot persoonlijke 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.
Opmerking
Aanroepstackgegevens voor de verzendende assembly worden 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 tot leden. De
Workerklasse 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.Opmerking
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 hoe de RestrictedMemberAccess vlag wordt gebruikt 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 ge marshalld binnen de grenzen van het toepassingsdomein. De klasse heeft twee AccessPrivateMethod methodeoverbelastingen die dynamische methoden verzenden en uitvoeren. De eerste overbelasting verzendt een dynamische methode die de privémethode PrivateMethod van de Worker klasse aanroept en de dynamische methode kan verzenden met of zonder JIT-zichtbaarheidscontroles. 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 en vervolgens een toepassingsdomein maakt, met behulp van de overbelasting van de AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) methode 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
AccessPrivateMethodmethode wordt uitgevoerd, worden JIT-zichtbaarheidscontroles afgedwongen. De dynamische methode mislukt wanneer deze wordt aangeroepen, omdat JIT-zichtbaarheidscontroles verhinderen dat deze toegang heeft tot de privémethode.De tweede keer dat de
AccessPrivateMethodmethode wordt uitgevoerd, worden JIT-zichtbaarheidscontroles overgeslagen. De dynamische methode mislukt wanneer deze wordt gecompileerd, omdat deInternettoekenningsset onvoldoende machtigingen verleent om zichtbaarheidscontroles over te slaan.
Het voorbeeld voegt ReflectionPermission samen met ReflectionPermissionFlag.RestrictedMemberAccess toe aan de toekenningsset. In het voorbeeld wordt vervolgens een tweede domein gemaakt, waarbij wordt opgegeven dat alle code die in het domein wordt uitgevoerd, de machtigingen in de nieuwe toekenningsset krijgt. In het voorbeeld wordt een exemplaar van de Worker klasse gemaakt in het nieuwe toepassingsdomein en worden beide overbelastingen van de AccessPrivateMethod methode uitgevoerd.
De eerste overbelasting van de
AccessPrivateMethodmethode wordt uitgevoerd en JIT-zichtbaarheidscontroles worden overgeslagen. De dynamische methode compileert en wordt 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 deWorkerklasse 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
AccessPrivateMethodmethode wordt uitgevoerd en er worden opnieuw JIT-zichtbaarheidscontroles overgeslagen. Deze keer mislukt de dynamische methode wanneer deze wordt gecompileerd, omdat deze toegang probeert te krijgen tot deinternalFirstChareigenschap 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 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($"{ex.GetType().Name} was thrown when the delegate was invoked.");
}
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType().Name} was thrown when the delegate was compiled.");
}
}
// 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($"{first} is the first character.");
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType().Name} was thrown when the delegate was compiled.");
}
}
// 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 om de naamruimte op te nemen wanneer u deze doorgeeft aan de CreateInstanceAndUnwrap methode. De naamruimte is standaard de naam van het project. Als het project bijvoorbeeld PartialTrust is, moet de klassenaam 'PartialTrust.Worker' zijn.