Compartilhar via


Demonstra Passo a passo: Emitindo um código em cenários de confiança parcial

Conjunto de usa a mesma API em confiança total ou parcial de emissão de reflexão, mas alguns recursos exigem permissões especiais de código parcialmente confiável. Além disso, emissão de reflexão possui um recurso, anonimamente hospedados métodos dinâmicos, que é projetado para ser usado com confiança parcial e por assemblies security transparent.

Observação

Antes de .NET Framework versão 3.5, emitindo o código necessário ReflectionPermission com o ReflectionPermissionFlag.ReflectionEmit sinalizador.Esta permissão é incluído por padrão no FullTrust e Intranet conjuntos de permissões nomeadas, mas não o Internet conjunto de permissão.Portanto, uma biblioteca pode ser usada de confiança parcial somente se ele tivesse o SecurityCriticalAttribute de atributo e também é executada uma Assert método para ReflectionEmit. Essas bibliotecas exigem análise cuidadosa de segurança porque os erros de codificação pode resultar em falhas de segurança.O .NET Framework 3.5 permite que o código a ser emitido em cenários de confiança parcial, sem emitir nenhum demandas de segurança, pois a geração de código é não inerentemente um privilegiado operação.Ou seja, o código gerado tem não mais permissões do assembly que emite a ele.Isso permite que as bibliotecas que emitem o código para ser transparente para a segurança e elimina a necessidade de declarar ReflectionEmit, de modo que a gravação de uma biblioteca de segura não exige que tal uma segurança completa revisão.

Essa explicação passo a passo ilustra as seguintes tarefas:

  • Configurando uma proteção simple, para testes parcialmente confiável código.

    Observação

    Esta é uma maneira simples de fazer experiências com o código em confiança parcial.Para executar o código que realmente vem em locais não confiáveis, consulte Como: Executar o código parcialmente confiável em um modo seguro.

  • Execução de código em domínios de aplicativo parcialmente confiável.

  • Usando anonimamente hospedado métodos dinâmicos para emitir e executar o código em confiança parcial.

Para obter mais informações sobre a emissão de código em cenários de confiança parcial, consulte Problemas de segurança em reflexão emitir.

Para obter uma lista completa do código mostrado nesses procedimentos, consulte o seção exemplo no final desta explicação passo a passo.

Configurando locais parcialmente confiáveis

Dois procedimentos a seguir mostram como configurar locais a partir do qual você pode testar o código com confiança parcial.

  • O primeiro procedimento mostra como criar um domínio de aplicativo no modo seguro no qual código recebe permissões de Internet.

  • O segundo procedimento mostra como adicionar ReflectionPermission com o ReflectionPermissionFlag.RestrictedMemberAccess sinalizador a um domínio de aplicativo parcialmente confiável, para permitir o acesso a dados privados em assemblies de confiança igual ou menor.

Criar domínios de aplicativo no modo seguro

Para criar um domínio de aplicativo no qual seus assemblies são executados com confiança parcial, você deve especificar o conjunto de permissões para ser concedido aos assemblies usando o AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) sobrecarga do método para criar o domínio de aplicativo. A maneira mais fácil para especificar o conjunto de concessão é recuperar um conjunto de diretiva de segurança de permissões nomeado.

O procedimento a seguir cria um domínio de aplicativo no modo seguro que executa o seu código com confiança parcial, para testar os cenários em que o código emitido pode acessar somente os membros públicos de tipos públicos. Um procedimento subseqüente mostra como adicionar RestrictedMemberAccess, para testar os cenários em que o código emitido pode acessar confidenciais tipos e membros nos assemblies que são concedidos permissões igual ou menor.

Para criar um domínio de aplicativo com confiança parcial

  1. Crie uma permissão definida para conceder aos assemblies no domínio de aplicativo no modo seguro. Nesse caso, o conjunto de permissões da zona da Internet é usado.

    Dim ev As New Evidence()
    ev.AddHostEvidence(new Zone(SecurityZone.Internet))
    Dim pset As New NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev))
    
    Evidence ev = new Evidence();
    ev.AddHostEvidence(new Zone(SecurityZone.Internet));
    PermissionSet pset = new NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev));
    
  2. Criar um AppDomainSetup o objeto para inicializar o domínio de aplicativo com um caminho de aplicativo.

    Observação

    Para simplificar, este exemplo de código usa a pasta atual.Para executar o código que realmente vem da Internet, use uma pasta separada para o código não confiável, conforme descrito em Como: Executar o código parcialmente confiável em um modo seguro.

    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = "."
    
    AppDomainSetup adSetup = new AppDomainSetup();
    adSetup.ApplicationBase = ".";
    
  3. Crie o domínio de aplicativo, especificando as informações de configuração do domínio de aplicativo e a concessão definido para todos os assemblies que são executados no domínio do aplicativo.

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

    O último parâmetro da AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) sobrecarga do método permite que você especificar um conjunto de módulos (assemblies) que devem receber confiança total, em vez do conjunto de concessão do domínio de aplicativo. Não é necessário especificar o .NET Framework assemblies que seu aplicativo usa, pois esses assemblies no cache global de assemblies. Assemblies no cache global de assemblies são sempre totalmente confiáveis. Você pode usar esse parâmetro para especificar os assemblies de nome forte que não estão no cache global de assemblies.

Adicionando RestrictedMemberAccess a domínios em modo seguro

Aplicativos de host podem permitir que anonimamente hospedados métodos dinâmicos ter acesso a dados privados em assemblies que têm níveis de confiança iguais ou menor que o nível de confiança do assembly que emite o código. Para habilitar essa possibilidade restrita de ignorar verificações de visibilidade do just-in-time (JIT), o aplicativo host adiciona uma ReflectionPermission de objeto com o ReflectionPermissionFlag.RestrictedMemberAccess o sinalizador (RMA) para o conjunto de concessão.

Por exemplo, um host pode conceder permissões de Internet de aplicativos de Internet mais RMA, para que um aplicativo da Internet pode emitir código que acessa dados privados em seus próprios assemblies. Como o acesso é limitado a assemblies de confiança igual ou menor, um aplicativo da Internet não pode acessar os membros dos assemblies totalmente confiáveis, como .NET Framework assemblies.

Observação

Para evitar a elevação de privilégio, informações de pilha para o assembly de emissão são incluídas quando hospedados anonimamente métodos dinâmicos são construídos.Quando o método é chamado, as informações de pilha são verificadas.Portanto, um método dinâmico anonimamente hospedado que é chamado de código totalmente confiável ainda é limitado ao nível de confiança do assembly de emissão.

Para criar um domínio de aplicativo com confiança parcial plus RMA

  1. Criar uma nova ReflectionPermission de objeto com o RestrictedMemberAccess (RMA) sinalizar e usar o PermissionSet.SetPermission método para adicionar a permissão para o conjunto de concessão.

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

    O AddPermission método adiciona ao conjunto de conceder a permissão se ela já não está incluída. Se a permissão já está incluída no conjunto de concessão, os sinalizadores especificados são adicionados à permissão existente.

    Observação

    RMA é um recurso de anonimamente hospedados métodos dinâmicos.Quando os métodos dinâmicos comuns ignorar verificações de visibilidade do JIT, o código emitido requer confiança total.

  2. Criar o domínio de aplicativo, especificando as informações de configuração do domínio de aplicativo e a concessão definido.

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

Execução de código em domínios de aplicativo no modo seguro

O procedimento a seguir explica como definir uma classe usando os métodos que podem ser executados em um domínio de aplicativo, como criar uma instância da classe do domínio e como executar seus métodos.

Para definir e executar um método em um domínio de aplicativo

  1. Definir uma classe que deriva de MarshalByRefObject. Isso permite criar instâncias da classe em outros domínios de aplicativo e fazer chamadas de método limites de domínio de aplicativo. A classe neste exemplo é chamada Worker.

    Public Class Worker
        Inherits MarshalByRefObject
    
    public class Worker : MarshalByRefObject
    {
    
  2. Defina um método público que contém o código que você deseja executar. Neste exemplo, o código emite um método dinâmico simples, cria um delegado para executar o método e invoca o delegado.

    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. No seu programa principal, obtenha o nome de exibição do seu assembly. Esse nome é usado quando você cria instâncias de Worker classe no domínio de aplicativo no modo seguro.

    Dim asmName As String = [Assembly].GetExecutingAssembly().FullName
    
    String asmName = Assembly.GetExecutingAssembly().FullName;
    
  4. No seu programa principal, criar um domínio de aplicativo no modo seguro, conforme descrito em o primeiro procedimento nesta explicação. Não é necessário adicionar quaisquer permissões para o Internet conjunto de permissões, porque o SimpleEmitDemo método usa somente pública métodos.

  5. No seu programa principal, criar uma instância de Worker classe no domínio de aplicativo no modo seguro.

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

    O CreateInstanceAndUnwrap método cria o objeto no domínio de aplicativo de destino e retorna um proxy que pode ser usado para chamar as propriedades e métodos do objeto.

    Observação

    Se você usar esse código em Visual Studio, você deve alterar o nome da classe para incluir o espaço para nome. Por padrão, o namespace é o nome do projeto.Por exemplo, se o projeto for "partialtrust", o nome da classe deve ser "PartialTrust.Worker".

  6. Adicione código para chamar o SimpleEmitDemo método. A chamada for empacotada em limites de domínio do aplicativo e o código é executado no domínio de aplicativo no modo seguro.

    w.SimpleEmitDemo()
    
    w.SimpleEmitDemo();
    

Usando anonimamente hospedado métodos dinâmicos

Hospedado anonimamente métodos dinâmicos estão associados um assembly transparente que é fornecido pelo sistema. Portanto, o código que eles contêm é transparente. Métodos comuns de dinâmicos, por outro lado, devem ser associados com um módulo existente (seja diretamente especificado ou deduzido a partir de um tipo associado) e levar o seu nível de segurança do módulo.

Observação

A única maneira de associar um método dinâmico com o assembly que fornece hospedagem anônimo é usar os construtores que estão descritos no procedimento a seguir.Você não pode explicitamente especificar um módulo do assembly de hospedagem anônimo.

Os métodos dinâmicos comuns tem acesso aos membros internos do módulo que estão associados, ou para membros particulares do tipo que estão associados. Como anonimamente hospedados métodos dinâmicos são isolados do outro código, eles não possuem acesso a dados privados. No entanto, eles têm uma possibilidade restrita de ignorar verificações de visibilidade do JIT para acessar dados particulares. Essa capacidade é limitada a assemblies que têm níveis de confiança iguais ou menor que o nível de confiança do assembly que emite o código.

Para evitar a elevação de privilégio, informações de pilha para o assembly de emissão são incluídas quando hospedados anonimamente métodos dinâmicos são construídos. Quando o método é chamado, as informações de pilha são verificadas. Um método dinâmico anonimamente hospedado que é chamado de código totalmente confiável ainda é limitado para o nível de confiança do assembly que são emitidas a ele.

Para usar anonimamente hospedado métodos dinâmicos

  • Crie um método dinâmico anonimamente hospedado usando um construtor que não especifica um tipo ou um módulo associado.

    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);
    

    Se um método dinâmico anonimamente hospedado usa apenas tipos públicos e métodos, ele não requer acesso de membro restrito e não precisa pular verificações de visibilidade JIT.

    Nenhuma permissão especial é necessárias para emitir um método dinâmico, mas o código emitido requer as permissões que são exigidas pelos tipos e métodos que ele usa. Por exemplo, se o código emitido chama um método que acessa um arquivo, ele requer FileIOPermission. Se o nível de confiança não tiver essa permissão, uma exceção de segurança é lançada quando o código emitido é executado. O código mostrado aqui emite um método dinâmico que usa apenas o Console.WriteLine método. Portanto, o código pode ser executado a partir de locais parcialmente confiáveis.

  • Como alternativa, criar um método dinâmico anonimamente hospedado com possibilidade restrita para ignorar as verificações de visibilidade do JIT, usando o DynamicMethod(String, Type, Type[], Boolean) construtor e especificando true para o restrictedSkipVisibility parâmetro.

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

    A restrição é que o método dinâmico anonimamente hospedado pode acessar dados particulares somente em assemblies com níveis de confiança iguais ou menor que o nível de confiança do assembly de emissão. Por exemplo, se o método dinâmico está em execução com confiança de Internet, ele pode acessar dados particulares em outros assemblies que também estão em execução com confiança de Internet, mas ele não pode acessar dados particulares de .NET Framework assemblies. .NET Frameworkassemblies são instalados no cache global de assemblies e sempre são totalmente confiáveis.

    Hospedado anonimamente métodos dinâmicos podem usar essa possibilidade restrita para ignorar as verificações de visibilidade do JIT somente se o aplicativo host concede ReflectionPermission com o ReflectionPermissionFlag.RestrictedMemberAccess sinalizador. A demanda por essa permissão é feita quando o método é invocado.

    Observação

    Informações de pilha de chamada para o assembly de emissão são incluídas quando o método dinâmico é construído.Portanto, a solicitação é feita contra as permissões do assembly em vez do assembly que invoca o método de emissão.Isso impede que o código emitido sendo executado com permissões elevadas.

    O o exemplo de código completo no final desta explicação passo a passo demonstra o uso e as limitações de acesso de membro restrito. Sua Worker classe inclui um método que pode criar anonimamente hospedados métodos dinâmicos, com ou sem a capacidade de restrita para ignorar as verificações de visibilidade e o exemplo mostra o resultado da execução deste método em domínios de aplicativo que possuem níveis de confiança diferente.

    Observação

    A capacidade de restrita para ignorar as verificações de visibilidade é um recurso de anonimamente hospedados métodos dinâmicos.Quando os métodos dinâmicos comuns ignorar verificações de visibilidade do JIT, devem receber confiança total.

Exemplo

Descrição

O exemplo de código a seguir demonstra o uso do RestrictedMemberAccess o sinalizador para permitir anonimamente hospedado métodos dinâmicos para ignorar as verificações de visibilidade do JIT, mas somente quando o membro de destino está em um nível igual ou menor de confiança que o assembly que emite o código.

O exemplo define uma Worker classe que pode ser empacotado através de limites de domínio de aplicativo. A classe tem dois AccessPrivateMethod sobrecargas do método que emitir e executar métodos dinâmicos. A primeira sobrecarga emite um método dinâmico que chama particular PrivateMethod método de Worker classe e ele podem emitir o método dinâmico com ou sem JIT visibilidade verificações. A segunda sobrecarga emite um método dinâmico que acessa um internal propriedade (Friend Visual Basic propriedade) da String classe.

O exemplo usa um método auxiliar para criar uma concessão definida limitada a Internet permissões e cria um domínio de aplicativo usando o AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) sobrecarga do método para especificar que todo o código que executa no domínio usa este conjunto de concessão. O exemplo cria uma instância da Worker o domínio do aplicativo de classe e executa o AccessPrivateMethod método duas vezes.

  • Na primeira vez que o AccessPrivateMethod método é executado, verificações de visibilidade do JIT são impostas. O método dinâmico falha quando é chamado, porque as verificações de visibilidade do JIT impedem-lo de acessar o método particular.

  • Na segunda vez que o AccessPrivateMethod método é executado, verificações de visibilidade do JIT são ignoradas. O método dinâmico falha quando ele é compilado, porque o Internet conceder o conjunto não concede permissões suficientes para ignorar as verificações de visibilidade.

O exemplo adiciona ReflectionPermission com ReflectionPermissionFlag.RestrictedMemberAccess para o conjunto de concessão. O exemplo cria um segundo domínio, especificar que todo o código que executa no domínio recebe as permissões em um novo conjunto de concessão. O exemplo cria uma instância da Worker o novo domínio de aplicativo de classe e executa ambas sobrecargas da AccessPrivateMethod método.

  • A primeira sobrecarga da AccessPrivateMethod método é executado e verifica de visibilidade do JIT são ignorados. O método dinâmico compila e executa com êxito, porque o assembly que emite o código é o mesmo que o assembly que contém o método particular. Portanto, os níveis de confiança são iguais. Se o aplicativo que contém o Worker classe tinha vários assemblies, o mesmo processo seria bem-sucedida para qualquer um desses módulos, porque eles seriam todos no mesmo nível de confiança.

  • A segunda sobrecarga da AccessPrivateMethod método é executado e verifica novamente de visibilidade do JIT são ignorados. Neste momento, o método dinâmico falha quando ele é compilado, porque ele tenta acessar a internal FirstChar propriedade da String classe. O assembly que contém o String classe é totalmente confiável. Portanto, está em um nível mais alto de confiança ao conjunto que emite o código.

Essa comparação mostra como ReflectionPermissionFlag.RestrictedMemberAccess permite que o código parcialmente confiável ignorar as verificações de visibilidade para outros códigos parcialmente confiáveis sem comprometer a segurança do código confiável.

Código

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

Compilando o código

  • Se você criar este exemplo de código Visual Studio, você deve alterar o nome da classe para incluir o espaço para nome ao passá-lo para o CreateInstanceAndUnwrap método. Por padrão, o namespace é o nome do projeto. Por exemplo, se o projeto for "partialtrust", o nome da classe deve ser "PartialTrust.Worker".

Consulte também

Tarefas

Como: Executar o código parcialmente confiável em um modo seguro

Conceitos

Problemas de segurança em reflexão emitir