Procédure pas à pas : émission de code dans des scénarios de confiance partielleWalkthrough: Emitting Code in Partial Trust Scenarios

L’émission de réflexion utilise le même ensemble d’API en confiance totale ou partielle, mais certaines fonctionnalités nécessitent des autorisations spéciales dans le code avec confiance partielle.Reflection emit uses the same API set in full or partial trust, but some features require special permissions in partially trusted code. En outre, l’émission de réflexion a une fonctionnalité, des méthodes dynamiques hébergées anonymement, qui est conçue pour être utilisée avec une confiance partielle et par les assemblys transparents de sécurité.In addition, reflection emit has a feature, anonymously hosted dynamic methods, that is designed to be used with partial trust and by security-transparent assemblies.

Notes

Avant .NET Framework 3.5, l’émission de code nécessitait ReflectionPermission avec l’indicateur ReflectionPermissionFlag.ReflectionEmit.Before .NET Framework 3.5, emitting code required ReflectionPermission with the ReflectionPermissionFlag.ReflectionEmit flag. Par défaut, cette autorisation est comprise dans les jeux d’autorisations nommés FullTrust et Intranet, mais pas dans le jeu d’autorisations Internet.This permission is included by default in the FullTrust and Intranet named permission sets, but not in the Internet permission set. Par conséquent, une bibliothèque pourrait être utilisée avec une confiance partielle seulement si elle avait l’attribut SecurityCriticalAttribute et exécutait aussi une méthode Assert pour ReflectionEmit.Therefore, a library could be used from partial trust only if it had the SecurityCriticalAttribute attribute and also executed an Assert method for ReflectionEmit. Ces bibliothèques nécessitent une revue minutieuse de la sécurité, car les erreurs de codage peuvent entraîner des failles de sécurité.Such libraries require careful security review because coding errors could result in security holes. .NET Framework 3.5 permet au code d’être émis dans des scénarios de confiance partielle sans émettre de demandes de sécurité, car la génération de code n’est pas fondamentalement une opération nécessitant des privilèges.The .NET Framework 3.5 allows code to be emitted in partial trust scenarios without issuing any security demands, because generating code is not inherently a privileged operation. Autrement dit, le code généré n'a pas plus d'autorisations que l'assembly qui l'émet.That is, the generated code has no more permissions than the assembly that emits it. Ainsi, les bibliothèques qui émettent du code sont transparentes de sécurité et il devient inutile de déclarer ReflectionEmit puisque l’écriture d’une bibliothèque sécurisée ne nécessite pas une révision aussi approfondie de la sécurité.This enables libraries that emit code to be security-transparent and removes the need to assert ReflectionEmit, so that writing a secure library does not require such a thorough security review.

Cette procédure pas à pas décrit les tâches suivantes :This walkthrough illustrates the following tasks:

Pour plus d’informations sur l’émission de code dans des scénarios de confiance partielle, consultez Problèmes de sécurité dans l’émission de réflexion.For more information about emitting code in partial trust scenarios, see Security Issues in Reflection Emit.

Pour obtenir une liste complète du code utilisé dans ces procédures, consultez la section Exemple à la fin de cette procédure pas à pas.For a complete listing of the code shown in these procedures, see the Example section at the end of this walkthrough.

Configuration des emplacements partiellement fiablesSetting up Partially Trusted Locations

Les deux procédures suivantes montrent comment configurer des emplacements à partir desquels vous pouvez tester du code avec une confiance partielle.The following two procedures show how to set up locations from which you can test code with partial trust.

  • La première procédure montre comment créer un domaine d’application sandbox dans lequel le code a des autorisations Internet.The first procedure shows how to create a sandboxed application domain in which code is granted Internet permissions.

  • La seconde procédure montre comment ajouter ReflectionPermission avec l’indicateur ReflectionPermissionFlag.RestrictedMemberAccess à un domaine d’application partiellement fiable pour activer l’accès aux données privées dans des assemblys d’une confiance inférieure ou égale.The second procedure shows how to add ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag to a partially trusted application domain, to enable access to private data in assemblies of equal or lesser trust.

Création de domaines d’application sandboxCreating Sandboxed Application Domains

Pour créer un domaine d’application dans lequel vos assemblys s’exécutent avec une confiance partielle, vous devez spécifier le jeu d’autorisations à accorder aux assemblys en utilisant la surcharge de la méthode AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) pour créer le domaine d’application.To create an application domain in which your assemblies run with partial trust, you must specify the set of permissions to be granted to the assemblies by using the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload to create the application domain. Pour spécifier le jeu d’autorisations, le plus simple est de récupérer un jeu d’autorisations nommé auprès de la stratégie de sécurité.The easiest way to specify the grant set is to retrieve a named permission set from security policy.

La procédure suivante crée un domaine d’application sandbox qui exécute votre code avec une confiance partielle pour tester des scénarios dans lesquels le code émis peut accéder seulement à des membres publics de types public.The following procedure creates a sandboxed application domain that runs your code with partial trust, to test scenarios in which emitted code can access only public members of public types. La procédure qui vient après montre comment ajouter RestrictedMemberAccess pour tester des scénarios dans lesquels le code émis peut accéder aux types et aux membres non publics dans les assemblys bénéficiant d’autorisations inférieures ou égales.A subsequent procedure shows how to add RestrictedMemberAccess, to test scenarios in which emitted code can access nonpublic types and members in assemblies that are granted equal or lesser permissions.

Pour créer un domaine d’application avec une confiance partielleTo create an application domain with partial trust

  1. Créez un jeu d’autorisations à accorder aux assemblys dans le domaine d’application sandbox.Create a permission set to grant to the assemblies in the sandboxed application domain. Dans ce cas, le jeu d’autorisations de la zone Internet est utilisé.In this case, the permission set of the Internet zone is used.

    Evidence ev = new Evidence();
    ev.AddHostEvidence(new Zone(SecurityZone.Internet));
    PermissionSet pset = new NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev));
    
    Dim ev As New Evidence()
    ev.AddHostEvidence(new Zone(SecurityZone.Internet))
    Dim pset As New NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev))
    
  2. Créez un objet AppDomainSetup pour initialiser le domaine d’application avec un chemin d’application.Create an AppDomainSetup object to initialize the application domain with an application path.

    Important

    Pour simplifier, cet exemple de code utilise le dossier actif.For simplicity, this code example uses the current folder. Pour exécuter du code qui provient d’Internet, utilisez un dossier distinct pour le code non fiable, comme décrit dans Guide pratique pour exécuter du code d’un niveau de confiance partiel dans un bac à sable (sandbox).To run code that actually comes from the Internet, use a separate folder for the untrusted code, as described in How to: Run Partially Trusted Code in a Sandbox.

    AppDomainSetup adSetup = new AppDomainSetup();
    adSetup.ApplicationBase = ".";
    
    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = "."
    
  3. Créez le domaine d’application en spécifiant les informations de configuration du domaine d’application et le jeu d’autorisations accordé pour tous les assemblys qui s’exécutent dans le domaine d’application.Create the application domain, specifying the application domain setup information and the grant set for all assemblies that execute in the application domain.

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

    Le dernier paramètre de la surcharge de la méthode AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) vous permet de spécifier un ensemble d’assemblys auxquels une confiance totale est accordée, à la place du jeu d’autorisations du domaine d’application.The last parameter of the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload enables you to specify a set of assemblies that are to be granted full trust, instead of the grant set of the application domain. Il n’est pas nécessaire de spécifier les assemblys .NET Framework utilisés par votre application, car ces assemblys se trouvent dans le Global Assembly Cache.You do not have to specify the .NET Framework assemblies that your application uses, because those assemblies are in the global assembly cache. Les assemblys présents dans le Global Assembly Cache sont toujours totalement fiables.Assemblies in the global assembly cache are always fully trusted. Vous pouvez utiliser ce paramètre pour spécifier des assemblys avec nom fort qui ne sont pas dans le Global Assembly Cache.You can use this parameter to specify strong-named assemblies that are not in the global assembly cache.

Ajout de RestrictedMemberAccess à des domaines sandboxAdding RestrictedMemberAccess to Sandboxed Domains

Les applications hôtes peuvent autoriser les méthodes dynamiques hébergées anonymement à accéder aux données privées dans les assemblys qui ont des niveaux de confiance inférieurs ou égaux au niveau de confiance de l’assembly qui émet le code.Host applications can allow anonymously hosted dynamic methods to have access to private data in assemblies that have trust levels equal to or less than the trust level of the assembly that emits the code. Pour permettre cette possibilité limitée d’ignorer les contrôles de visibilité juste-à-temps (JIT), l’application hôte ajoute un objet ReflectionPermission avec l’indicateur ReflectionPermissionFlag.RestrictedMemberAccess (RMA) au jeu d’autorisations.To enable this restricted ability to skip just-in-time (JIT) visibility checks, the host application adds a ReflectionPermission object with the ReflectionPermissionFlag.RestrictedMemberAccess (RMA) flag to the grant set.

Par exemple, un hôte peut accorder des autorisations Internet plus RMA à des applications Internet, pour qu’une application Internet puisse émettre du code qui accède aux données privées dans ses propres assemblys.For example, a host might grant Internet applications Internet permissions plus RMA, so that an Internet application can emit code that accesses private data in its own assemblies. Étant donné que l’accès est limité aux assemblys de confiance inférieure ou égale, une application Internet ne peut pas accéder aux membres des assemblys entièrement fiables, comme les assemblys .NET Framework.Because the access is limited to assemblies of equal or lesser trust, an Internet application cannot access members of fully trusted assemblies such as .NET Framework assemblies.

Notes

Pour empêcher une élévation de privilèges, les informations de pile de l’assembly émetteur sont incluses lors de la construction des méthodes dynamiques hébergées anonymement.To prevent elevation of privilege, stack information for the emitting assembly is included when anonymously hosted dynamic methods are constructed. Quand la méthode est appelée, les informations de pile sont vérifiées.When the method is invoked, the stack information is checked. Par conséquent, une méthode dynamique hébergée anonymement qui est appelée à partir d’un code totalement fiable est toujours limitée au niveau de confiance de l’assembly émetteur.Thus, an anonymously hosted dynamic method that is invoked from fully trusted code is still limited to the trust level of the emitting assembly.

Pour créer un domaine d’application avec une confiance partielle plus RMATo create an application domain with partial trust plus RMA

  1. Créez un objet ReflectionPermission avec l’indicateur RestrictedMemberAccess (RMA) et utilisez la méthode PermissionSet.SetPermission pour ajouter l’autorisation au jeu d’autorisations.Create a new ReflectionPermission object with the RestrictedMemberAccess (RMA) flag, and use the PermissionSet.SetPermission method to add the permission to the grant set.

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

    La méthode AddPermission ajoute l’autorisation au jeu d’autorisations si elle n’y est pas déjà.The AddPermission method adds the permission to the grant set if it is not already included. Si l’autorisation est déjà dans le jeu d’autorisations, les indicateurs spécifiés sont ajoutés à l’autorisation existante.If the permission is already included in the grant set, the specified flags are added to the existing permission.

    Notes

    RMA est une fonctionnalité des méthodes dynamiques hébergées anonymement.RMA is a feature of anonymously hosted dynamic methods. Quand des méthodes dynamiques ordinaires ignorent les contrôles de visibilité JIT, le code émis nécessite une confiance totale.When ordinary dynamic methods skip JIT visibility checks, the emitted code requires full trust.

  2. Créez le domaine d’application en spécifiant les informations de configuration du domaine d’application et le jeu d’autorisations.Create the application domain, specifying the application domain setup information and the grant set.

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

Exécution de code dans des domaines d’application sandboxRunning Code in Sandboxed Application Domains

La procédure suivante explique comment définir une classe en utilisant des méthodes qui peuvent être exécutées dans un domaine d’application, comment créer une instance de la classe dans le domaine et comment exécuter ses méthodes.The following procedure explains how to define a class by using methods that can be executed in an application domain, how to create an instance of the class in the domain, and how to execute its methods.

Pour définir et exécuter une méthode dans un domaine d’applicationTo define and execute a method in an application domain

  1. Définissez une classe qui dérive de MarshalByRefObject.Define a class that derives from MarshalByRefObject. Cette opération vous permet de créer des instances de la classe dans d’autres domaines d’application et d’effectuer des appels de méthode à travers les limites du domaine d’application.This enables you to create instances of the class in other application domains and to make method calls across application domain boundaries. Dans cet exemple, la classe est nommée Worker.The class in this example is named Worker.

    public class Worker : MarshalByRefObject
    {
    
    Public Class Worker
        Inherits MarshalByRefObject
    
  2. Définissez une méthode publique qui contient le code que vous voulez exécuter.Define a public method that contains the code you want to execute. Dans cet exemple, le code émet une méthode dynamique simple, crée un délégué pour exécuter la méthode et appelle le délégué.In this example, the code emits a simple dynamic method, creates a delegate to execute the method, and invokes the delegate.

    public void SimpleEmitDemo()
    {
        DynamicMethod meth = new DynamicMethod("", null, null);
        ILGenerator il = meth.GetILGenerator();
        il.EmitWriteLine("Hello, World!");
        il.Emit(OpCodes.Ret);
    
        Test1 t1 = (Test1) meth.CreateDelegate(typeof(Test1));
        t1();
    }
    
    Public Sub SimpleEmitDemo()
    
        Dim meth As DynamicMethod = new DynamicMethod("", Nothing, Nothing)
        Dim il As ILGenerator = meth.GetILGenerator()
        il.EmitWriteLine("Hello, World!")
        il.Emit(OpCodes.Ret)
    
        Dim t1 As Test1 = CType(meth.CreateDelegate(GetType(Test1)), Test1)
        t1()
    End Sub
    
  3. Dans votre programme principal, obtenez le nom d’affichage de votre assembly.In your main program, get the display name of your assembly. Ce nom est utilisé quand vous créez des instances de la classe Worker dans le domaine d’application sandbox.This name is used when you create instances of the Worker class in the sandboxed application domain.

    String asmName = typeof(Worker).Assembly.FullName;
    
    Dim asmName As String = GetType(Worker).Assembly.FullName
    
  4. Dans votre programme principal, créez un domaine d’application sandbox, comme décrit dans la première procédure de cet article.In your main program, create a sandboxed application domain, as described in the first procedure in this walkthrough. Vous ne devez pas ajouter des autorisations au jeu d’autorisations Internet, car la méthode SimpleEmitDemo utilise uniquement des méthodes publiques.You do not have to add any permissions to the Internet permission set, because the SimpleEmitDemo method uses only public methods.

  5. Dans votre programme principal, créez une instance de la classe Worker dans le domaine d’application sandbox.In your main program, create an instance of the Worker class in the sandboxed application domain.

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

    La méthode CreateInstanceAndUnwrap crée l’objet dans le domaine d’application cible et retourne un proxy qui peut être utilisé pour appeler les propriétés et les méthodes de l’objet.The CreateInstanceAndUnwrap method creates the object in the target application domain and returns a proxy that can be used to call the properties and methods of the object.

    Notes

    Si vous utilisez ce code dans Visual Studio, vous devez changer le nom de la classe pour y inclure l’espace de noms.If you use this code in Visual Studio, you must change the name of the class to include the namespace. Par défaut, l’espace de noms est le nom du projet.By default, the namespace is the name of the project. Par exemple, si le projet est « PartialTrust », le nom de la classe doit être « PartialTrust.Worker ».For example, if the project is "PartialTrust", the class name must be "PartialTrust.Worker".

  6. Ajoutez le code pour appeler la méthode SimpleEmitDemo.Add code to call the SimpleEmitDemo method. L’appel est marshalé à travers la limite du domaine d’application et le code est exécuté dans le domaine d’application sandbox.The call is marshaled across the application domain boundary, and the code is executed in the sandboxed application domain.

    w.SimpleEmitDemo();
    
    w.SimpleEmitDemo()
    

Utilisation de méthodes dynamiques hébergées anonymementUsing Anonymously Hosted Dynamic Methods

Les méthodes dynamiques hébergées anonymement sont associées à un assembly transparent fourni par le système.Anonymously hosted dynamic methods are associated with a transparent assembly that is provided by the system. Par conséquent, le code qu’elles contiennent est transparent.Therefore, the code they contain is transparent. Les méthodes dynamiques ordinaires doivent quant à elles être associées à un module existant (qu’il soit spécifié directement ou inféré depuis un type associé) et prendre leur niveau de sécurité de ce module.Ordinary dynamic methods, on the other hand, must be associated with an existing module (whether directly specified or inferred from an associated type), and take their security level from that module.

Notes

La seule façon d’associer une méthode dynamique à l’assembly qui fournit l’hébergement anonyme est d’utiliser les constructeurs qui sont décrits dans la procédure suivante.The only way to associate a dynamic method with the assembly that provides anonymous hosting is to use the constructors that are described in the following procedure. Vous ne pouvez pas spécifier explicitement un module dans l’assembly hébergeur anonyme.You cannot explicitly specify a module in the anonymous hosting assembly.

Les méthodes dynamiques ordinaires ont accès aux membres internes du module auquel elles sont associées ou aux membres privés du type auquel elles sont associées.Ordinary dynamic methods have access to the internal members of the module they are associated with, or to the private members of the type they are associated with. Comme les méthodes dynamiques hébergées anonymement sont isolées du reste du code, elles n’ont pas accès aux données privées.Because anonymously hosted dynamic methods are isolated from other code, they do not have access to private data. Toutefois, elles ont une possibilité limitée d’ignorer les contrôles de visibilité JIT pour accéder aux données privées.However, they do have a restricted ability to skip JIT visibility checks to gain access to private data. Cette possibilité est limitée aux assemblys qui ont des niveaux de confiance inférieurs ou égaux au niveau de confiance de l’assembly qui émet le code.This ability is limited to assemblies that have trust levels equal to or less than the trust level of the assembly that emits the code.

Pour empêcher une élévation de privilèges, les informations de pile de l’assembly émetteur sont incluses lors de la construction des méthodes dynamiques hébergées anonymement.To prevent elevation of privilege, stack information for the emitting assembly is included when anonymously hosted dynamic methods are constructed. Quand la méthode est appelée, les informations de pile sont vérifiées.When the method is invoked, the stack information is checked. Une méthode dynamique hébergée anonymement qui est appelée à partir d’un code totalement fiable est toujours limitée au niveau de confiance de l’assembly émetteur.An anonymously hosted dynamic method that is invoked from fully trusted code is still limited to the trust level of the assembly that emitted it.

Pour utiliser des méthodes dynamiques hébergées anonymementTo use anonymously hosted dynamic methods

  • Créez une méthode dynamique hébergée anonymement en utilisant un constructeur qui ne spécifie pas un module ou un type associé.Create an anonymously hosted dynamic method by using a constructor that does not specify an associated module or type.

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

    Si une méthode dynamique hébergée anonymement utilise seulement des méthodes et des types publics, elle ne nécessite pas un accès restreint aux membres et n’a pas à ignorer les contrôles de visibilité JIT.If an anonymously hosted dynamic method uses only public types and methods, it does not require restricted member access and does not have to skip JIT visibility checks.

    Aucune autorisation spéciale n’est nécessaire pour émettre une méthode dynamique, mais le code émis nécessite les autorisations demandées par les types et les méthodes qu’il utilise.No special permissions are required to emit a dynamic method, but the emitted code requires the permissions that are demanded by the types and methods it uses. Par exemple, si le code émis appelle une méthode qui accède à un fichier, il nécessite FileIOPermission.For example, if the emitted code calls a method that accesses a file, it requires FileIOPermission. Si le niveau de confiance n’inclut pas cette autorisation, une exception de sécurité est levée quand le code émis est exécuté.If the trust level does not include that permission, a security exception is thrown when the emitted code is executed. Le code montré ici émet une méthode dynamique qui utilise seulement la méthode Console.WriteLine.The code shown here emits a dynamic method that uses only the Console.WriteLine method. Par conséquent, le code peut être exécuté à partir d’emplacements partiellement fiables.Therefore, the code can be executed from partially trusted locations.

  • Vous pouvez aussi créer une méthode dynamique hébergée anonymement avec une possibilité limitée d’ignorer les contrôles de visibilité JIT, en utilisant le constructeur DynamicMethod(String, Type, Type[], Boolean) et en spécifiant true pour le paramètre restrictedSkipVisibility.Alternatively, create an anonymously hosted dynamic method with restricted ability to skip JIT visibility checks, by using the DynamicMethod(String, Type, Type[], Boolean) constructor and specifying true for the restrictedSkipVisibility parameter.

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

    La restriction est que la méthode dynamique hébergée anonymement peut accéder aux données privées seulement dans les assemblys avec des niveaux de confiance inférieurs ou égaux à celui de l’assembly émetteur.The restriction is that the anonymously hosted dynamic method can access private data only in assemblies with trust levels equal to or less than the trust level of the emitting assembly. Par exemple, si la méthode dynamique s’exécute avec une confiance Internet, elle peut accéder aux données privées d’autres assemblys qui s’exécutent aussi avec la confiance Internet, mais elle ne peut pas accéder aux données privées des assemblys .NET Framework.For example, if the dynamic method is executing with Internet trust, it can access private data in other assemblies that are also executing with Internet trust, but it cannot access private data of .NET Framework assemblies. Les assemblys .NET Framework sont installés dans le Global Assembly Cache et sont toujours entièrement fiables..NET Framework assemblies are installed in the global assembly cache and are always fully trusted.

    Les méthodes dynamiques hébergées anonymement peuvent utiliser cette possibilité limitée d’ignorer les contrôles de visibilité JIT seulement si l’application hôte accorde ReflectionPermission avec l’indicateur ReflectionPermissionFlag.RestrictedMemberAccess.Anonymously hosted dynamic methods can use this restricted ability to skip JIT visibility checks only if the host application grants ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag. La demande de cette autorisation est effectuée quand la méthode est appelée.The demand for this permission is made when the method is invoked.

    Notes

    Les informations de la pile des appels de l’assembly émetteur sont incluses lors de la construction de la méthode dynamique.Call stack information for the emitting assembly is included when the dynamic method is constructed. Par conséquent, la demande porte sur les autorisations de l’assembly émetteur au lieu de l’assembly qui appelle la méthode.Therefore, the demand is made against the permissions of the emitting assembly instead of the assembly that invokes the method. Ceci empêche l’exécution du code émis avec des autorisations élevées.This prevents the emitted code from being executed with elevated permissions.

    L’exemple de code complet à la fin de cette procédure pas à pas montre l’utilisation et les limitations de l’accès restreint aux membres.The complete code example at the end of this walkthrough demonstrates the use and limitations of restricted member access. Sa classe Worker comprend une méthode qui peut créer des méthodes dynamiques hébergées anonymement avec ou sans la possibilité limitée d’ignorer les contrôles de visibilité. L’exemple montre le résultat de l’exécution de cette méthode dans des domaines d’application qui ont des niveaux de confiance différents.Its Worker class includes a method that can create anonymously hosted dynamic methods with or without the restricted ability to skip visibility checks, and the example shows the result of executing this method in application domains that have different trust levels.

    Notes

    La possibilité limitée d’ignorer les contrôles de visibilité est une fonctionnalité des méthodes dynamiques hébergées anonymement.The restricted ability to skip visibility checks is a feature of anonymously hosted dynamic methods. Quand des méthodes dynamiques ordinaires ignorent les contrôles de visibilité JIT, une confiance totale leur est accordée.When ordinary dynamic methods skip JIT visibility checks, they must be granted full trust.

ExempleExample

DescriptionDescription

L’exemple de code suivant montre l’utilisation de l’indicateur RestrictedMemberAccess pour permettre aux méthodes dynamiques hébergées anonymement d’ignorer les contrôles de visibilité JIT, mais seulement quand le membre cible est à un niveau de confiance inférieur ou égal à celui de l’assembly qui émet le code.The following code example demonstrates the use of the RestrictedMemberAccess flag to allow anonymously hosted dynamic methods to skip JIT visibility checks, but only when the target member is at an equal or lower level of trust than the assembly that emits the code.

L’exemple définit une classe Worker qui peut être marshalée à travers les limites du domaine d’application.The example defines a Worker class that can be marshaled across application domain boundaries. La classe a deux surcharges de la méthode AccessPrivateMethod, qui émettent et exécutent des méthodes dynamiques.The class has two AccessPrivateMethod method overloads that emit and execute dynamic methods. La première surcharge émet une méthode dynamique qui appelle la méthode PrivateMethod privée de la classe Worker, et peut émettre la méthode dynamique avec ou sans contrôles de visibilité JIT.The first overload emits a dynamic method that calls the private PrivateMethod method of the Worker class, and it can emit the dynamic method with or without JIT visibility checks. La deuxième surcharge émet une méthode dynamique qui accède à une propriété internal (la propriété Friend en Visual Basic) de la classe String.The second overload emits a dynamic method that accesses an internal property (Friend property in Visual Basic) of the String class.

L’exemple utilise une méthode d’assistance pour créer un jeu d’autorisations limité aux autorisations Internet, puis crée un domaine d’application en utilisant la surcharge de la méthode AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) pour spécifier que tout le code qui s’exécute dans le domaine utilise ce jeu d’autorisations.The example uses a helper method to create a grant set limited to Internet permissions, and then creates an application domain, using the AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) method overload to specify that all code that executes in the domain uses this grant set. L’exemple crée une instance de la classe Worker dans le domaine d’application et exécute deux fois la méthode AccessPrivateMethod.The example creates an instance of the Worker class in the application domain, and executes the AccessPrivateMethod method two times.

  • La première fois que la méthode AccessPrivateMethod est exécutée, les contrôles de visibilité JIT sont appliqués.The first time the AccessPrivateMethod method is executed, JIT visibility checks are enforced. La méthode dynamique échoue quand elle est appelée, car les contrôles de visibilité JIT l’empêchent d’accéder à la méthode privée.The dynamic method fails when it is invoked, because JIT visibility checks prevent it from accessing the private method.

  • La seconde fois que la méthode AccessPrivateMethod est exécutée, les contrôles de visibilité JIT sont ignorés.The second time the AccessPrivateMethod method is executed, JIT visibility checks are skipped. La méthode dynamique échoue lors de la compilation, car le jeu d’autorisations Internet n’accorde pas d’autorisations suffisantes pour ignorer les contrôles de visibilité.The dynamic method fails when it is compiled, because the Internet grant set does not grant sufficient permissions to skip visibility checks.

L’exemple ajoute ReflectionPermission avec ReflectionPermissionFlag.RestrictedMemberAccess au jeu d’autorisations.The example adds ReflectionPermission with ReflectionPermissionFlag.RestrictedMemberAccess to the grant set. L’exemple crée ensuite un second domaine en spécifiant que tout le code qui s’exécute dans le domaine reçoit les autorisations du jeu d’autorisations.The example then creates a second domain, specifying that all code that executes in the domain is granted the permissions in the new grant set. L’exemple crée une instance de la classe Worker dans le nouveau domaine d’application et exécute les deux surcharges de la méthode AccessPrivateMethod.The example creates an instance of the Worker class in the new application domain, and executes both overloads of the AccessPrivateMethod method.

  • La première surcharge de la méthode AccessPrivateMethod est exécutée et les contrôles de visibilité JIT sont ignorés.The first overload of the AccessPrivateMethod method is executed, and JIT visibility checks are skipped. La méthode dynamique se compile et s’exécute correctement, car l’assembly qui émet le code est le même que l’assembly qui contient la méthode privée.The dynamic method compiles and executes successfully, because the assembly that emits the code is the same as the assembly that contains the private method. Par conséquent, les niveaux de confiance sont égaux.Therefore, the trust levels are equal. Si l’application qui contient la classe Worker avait plusieurs assemblys, le même processus réussirait pour chacun de ces assemblys, car ils seraient tous au même niveau de confiance.If the application that contains the Worker class had several assemblies, the same process would succeed for any one of those assemblies, because they would all be at the same trust level.

  • La seconde surcharge de la méthode AccessPrivateMethod est exécutée et les contrôles de visibilité JIT sont à nouveau ignorés.The second overload of the AccessPrivateMethod method is executed, and again JIT visibility checks are skipped. Cette fois, la méthode dynamique échoue lors de la compilation, car elle essaie d’accéder à la propriété internal FirstChar de la classe String.This time the dynamic method fails when it is compiled, because it tries to access the internal FirstChar property of the String class. L’assembly qui contient la classe String est totalement fiable.The assembly that contains the String class is fully trusted. Par conséquent, il est à un niveau de confiance plus élevé que l’assembly qui émet le code.Therefore, it is at a higher level of trust than the assembly that emits the code.

Cette comparaison montre comment ReflectionPermissionFlag.RestrictedMemberAccess permet à du code partiellement fiable d’ignorer les contrôles de visibilité pour un autre code partiellement fiable sans compromettre la sécurité du code de confiance.This comparison shows how ReflectionPermissionFlag.RestrictedMemberAccess enables partially trusted code to skip visibility checks for other partially trusted code without compromising the security of trusted code.

CodeCode

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

Compilation du codeCompiling the Code

  • Si vous générez cet exemple de code dans Visual Studio, vous devez changer le nom de la classe pour inclure l’espace de noms quand vous le passez à la méthode CreateInstanceAndUnwrap.If you build this code example in Visual Studio, you must change the name of the class to include the namespace when you pass it to the CreateInstanceAndUnwrap method. Par défaut, l’espace de noms est le nom du projet.By default, the namespace is the name of the project. Par exemple, si le projet est « PartialTrust », le nom de la classe doit être « PartialTrust.Worker ».For example, if the project is "PartialTrust", the class name must be "PartialTrust.Worker".

Voir aussiSee also