Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
A emit de reflexão utiliza o mesmo conjunto de API na confiança total ou parcial, mas algumas funcionalidades requerem permissões especiais em código parcialmente fidedigno. Além disso, a emit de reflexão tem uma funcionalidade, métodos dinâmicos alojados anonimamente, que foi concebida para ser utilizada com confiança parcial e por assemblagens transparentes de segurança.
Nota
Antes .NET Framework 3.5, é necessário ReflectionPermission emitir código com o ReflectionPermissionFlag.ReflectionEmit sinalizador. Esta permissão está incluída por predefinição nos FullTrust conjuntos de permissões e Intranet com nome, mas não no Internet conjunto de permissões. Por conseguinte, uma biblioteca só poderia ser utilizada a partir de confiança parcial se tivesse o SecurityCriticalAttribute atributo e também executasse um Assert método para ReflectionEmit. Estas bibliotecas requerem uma revisão de segurança cuidadosa porque os erros de codificação podem resultar em falhas de segurança. O .NET Framework 3.5 permite que o código seja emitido em cenários de fidedignidade parcial sem emitir quaisquer exigências de segurança, uma vez que gerar código não é inerentemente uma operação com privilégios. Ou seja, o código gerado não tem mais permissões do que a assemblagem que o emite. Isto permite que as bibliotecas que emitem código sejam transparentes em segurança e removem a necessidade de afirmar ReflectionEmit, para que a escrita de uma biblioteca segura não exija uma revisão de segurança tão completa.
Estas instruções ilustram as seguintes tarefas:
Configurar um sandbox simples para testar código parcialmente fidedigno.
Importante
Esta é uma forma simples de experimentar código em confiança parcial. Para executar código proveniente de localizações não fidedignas, veja Como: Executar Código Parcialmente Fidedigno num Sandbox.
Executar código em domínios de aplicações parcialmente fidedignos.
Utilizar métodos dinâmicos alojados anonimamente para emitir e executar código em confiança parcial.
Para obter mais informações sobre a emissão de código em cenários de fidedignidade parcial, veja Problemas de Segurança em Emite de Reflexão.
Para obter uma lista completa do código apresentado nestes procedimentos, consulte a secção Exemplo no final destas instruções.
Configurar Localizações Parcialmente Fidedignas
Os dois procedimentos seguintes mostram como configurar localizações a partir das quais pode testar código com confiança parcial.
O primeiro procedimento mostra como criar um domínio de aplicação em sandbox no qual é concedida permissão de Internet ao código.
O segundo procedimento mostra como adicionar ReflectionPermission com o ReflectionPermissionFlag.RestrictedMemberAccess sinalizador a um domínio de aplicação parcialmente fidedigno, para permitir o acesso a dados privados em assemblagens de confiança igual ou menor.
Criar Domínios de Aplicações em Sandbox
Para criar um domínio de aplicação no qual as assemblagens são executadas com confiança parcial, tem de especificar o conjunto de permissões a conceder às assemblagens através da sobrecarga do AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) método para criar o domínio da aplicação. A forma mais fácil de especificar o conjunto de concessões é obter um conjunto de permissões com nome da política de segurança.
O procedimento seguinte cria um domínio de aplicação em sandbox que executa o código com confiança parcial, para testar cenários em que o código emitido pode aceder apenas a membros públicos de tipos públicos. Um procedimento subsequente mostra como adicionar RestrictedMemberAccess, para testar cenários em que o código emitido pode aceder a tipos e membros não públicos em assemblagens que recebem permissões iguais ou menores.
Para criar um domínio de aplicação com confiança parcial
Crie um conjunto de permissões para conceder às assemblagens no domínio da aplicação em sandbox. Neste caso, é utilizado o conjunto de permissões da zona da Internet.
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))Crie um AppDomainSetup objeto para inicializar o domínio da aplicação com um caminho de aplicação.
Importante
Para simplificar, este exemplo de código utiliza a pasta atual. Para executar código efetivamente proveniente da Internet, utilize uma pasta separada para o código não fidedigno, conforme descrito em Como: Executar Código Parcialmente Fidedigno num Sandbox.
AppDomainSetup adSetup = new AppDomainSetup(); adSetup.ApplicationBase = ".";Dim adSetup As New AppDomainSetup() adSetup.ApplicationBase = "."Crie o domínio da aplicação, especificando as informações de configuração do domínio da aplicação e o conjunto de concessões para todas as assemblagens que são executadas no domínio da aplicação.
AppDomain ad = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, null);Dim ad As AppDomain = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, Nothing)O último parâmetro da sobrecarga do AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) método permite-lhe especificar um conjunto de assemblagens a conceder confiança total, em vez do conjunto de concessões do domínio da aplicação. Não tem de especificar o .NET Framework assemblagens que a sua aplicação utiliza, uma vez que essas assemblagens estão na cache de assemblagem global. As assemblagens na cache de assemblagem global são sempre totalmente fidedignas. Pode utilizar este parâmetro para especificar assemblagens com nome forte que não estão na cache de assemblagem global.
Adicionar RestrictedMemberAccess a Domínios em Sandbox
As aplicações anfitriãs podem permitir que os métodos dinâmicos alojados anonimamente tenham acesso a dados privados em assemblagens com níveis de confiança iguais ou inferiores ao nível de confiança da assemblagem que emite o código. Para permitir que esta capacidade restrita ignore verificações de visibilidade just-in-time (JIT), a aplicação anfitriã adiciona um ReflectionPermission objeto com o ReflectionPermissionFlag.RestrictedMemberAccess sinalizador (RMA) ao conjunto de concessões.
Por exemplo, um anfitrião pode conceder permissões de Internet a aplicações de Internet mais RMA, para que uma aplicação de Internet possa emitir código que aceda a dados privados nas suas próprias assemblagens. Uma vez que o acesso está limitado a assemblagens de confiança igual ou menor, uma aplicação de Internet não pode aceder aos membros de assemblagens totalmente fidedignas, como .NET Framework assemblagens.
Nota
Para impedir a elevação de privilégios, as informações de pilha para a assemblagem emissora são incluídas quando são construídos métodos dinâmicos alojados anonimamente. Quando o método é invocado, as informações da pilha são verificadas. Assim, um método dinâmico alojado anonimamente que é invocado a partir de código totalmente fidedigno ainda está limitado ao nível de confiança da assemblagem emissora.
Para criar um domínio de aplicação com confiança parcial mais RMA
Crie um novo ReflectionPermission objeto com o RestrictedMemberAccess sinalizador (RMA) e utilize o PermissionSet.SetPermission método para adicionar a permissão ao conjunto de concessões.
pset.SetPermission( new ReflectionPermission( ReflectionPermissionFlag.RestrictedMemberAccess));pset.SetPermission( _ New ReflectionPermission( _ ReflectionPermissionFlag.RestrictedMemberAccess))O AddPermission método adiciona a permissão ao conjunto de concessões se ainda não estiver incluído. Se a permissão já estiver incluída no conjunto de concessões, os sinalizadores especificados serão adicionados à permissão existente.
Nota
O RMA é uma funcionalidade de métodos dinâmicos alojados anonimamente. Quando os métodos dinâmicos comuns ignoram as verificações de visibilidade do JIT, o código emitido requer confiança total.
Crie o domínio da aplicação, especificando as informações de configuração do domínio da aplicação e o conjunto de concessões.
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)
Código em Execução em Domínios de Aplicações em Sandbox
O procedimento seguinte explica como definir uma classe com métodos que podem ser executados num domínio de aplicação, como criar uma instância da classe no domínio e como executar os respetivos métodos.
Para definir e executar um método num domínio de aplicação
Defina uma classe derivada de MarshalByRefObject. Isto permite-lhe criar instâncias da classe noutros domínios de aplicação e efetuar chamadas de método através dos limites do domínio da aplicação. A classe neste exemplo tem o nome
Worker.public class Worker : MarshalByRefObject {Public Class Worker Inherits MarshalByRefObjectDefina um método público que contenha o código que pretende 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 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 SubNo programa principal, obtenha o nome a apresentar da sua assemblagem. Este nome é utilizado quando cria instâncias da
Workerclasse no domínio da aplicação em sandbox.String asmName = typeof(Worker).Assembly.FullName;Dim asmName As String = GetType(Worker).Assembly.FullNameNo seu programa principal, crie um domínio de aplicação em sandbox, conforme descrito no primeiro procedimento nestas instruções. Não tem de adicionar permissões ao
Internetconjunto de permissões, porque oSimpleEmitDemométodo utiliza apenas métodos públicos.No seu programa principal, crie uma instância da
Workerclasse no domínio da aplicação em sandbox.Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");Dim w As Worker = _ CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)O CreateInstanceAndUnwrap método cria o objeto no domínio da aplicação de destino e devolve um proxy que pode ser utilizado para chamar as propriedades e métodos do objeto.
Nota
Se utilizar este código no Visual Studio, tem de alterar o nome da classe para incluir o espaço de nomes. Por predefinição, o espaço de nomes é o nome do projeto. Por exemplo, se o projeto for "PartialTrust", o nome da classe tem de ser "PartialTrust.Worker".
Adicione código para chamar o
SimpleEmitDemométodo . A chamada é feita através do limite do domínio da aplicação e o código é executado no domínio da aplicação em sandbox.w.SimpleEmitDemo();w.SimpleEmitDemo()
Utilizar Métodos Dinâmicos Alojados Anonimamente
Os métodos dinâmicos alojados anonimamente estão associados a uma assemblagem transparente fornecida pelo sistema. Por conseguinte, o código que contêm é transparente. Os métodos dinâmicos comuns, por outro lado, têm de ser associados a um módulo existente (quer sejam diretamente especificados ou inferidos a partir de um tipo associado) e tirar o nível de segurança desse módulo.
Nota
A única forma de associar um método dinâmico à assemblagem que fornece alojamento anónimo é utilizar os construtores descritos no procedimento seguinte. Não pode especificar explicitamente um módulo na assemblagem de alojamento anónimo.
Os métodos dinâmicos comuns têm acesso aos membros internos do módulo ao qual estão associados ou aos membros privados do tipo a que estão associados. Uma vez que os métodos dinâmicos alojados anonimamente estão isolados de outro código, não têm acesso a dados privados. No entanto, têm uma capacidade restrita de ignorar as verificações de visibilidade do JIT para obter acesso a dados privados. Esta capacidade está limitada a assemblagens com níveis de confiança iguais ou inferiores ao nível de confiança da assemblagem que emite o código.
Para impedir a elevação de privilégios, as informações de pilha para a assemblagem emissora são incluídas quando são construídos métodos dinâmicos alojados anonimamente. Quando o método é invocado, as informações da pilha são verificadas. Um método dinâmico alojado anonimamente que é invocado a partir de código totalmente fidedigno ainda está limitado ao nível de confiança da assemblagem que o emitiu.
Para utilizar métodos dinâmicos alojados anonimamente
Crie um método dinâmico alojado anonimamente com um construtor que não especifique um módulo ou tipo associado.
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)Se um método dinâmico alojado anonimamente utilizar apenas tipos e métodos públicos, não requer acesso restrito aos membros e não tem de ignorar as verificações de visibilidade do JIT.
Não são necessárias permissões especiais para emitir um método dinâmico, mas o código emitido requer as permissões exigidas pelos tipos e métodos que utiliza. Por exemplo, se o código emitido chamar um método que acede a um ficheiro, é necessário FileIOPermission. Se o nível de confiança não incluir essa permissão, é emitida uma exceção de segurança quando o código emitido é executado. O código aqui apresentado emite um método dinâmico que utiliza apenas o Console.WriteLine método . Por conseguinte, o código pode ser executado a partir de localizações parcialmente fidedignas.
Em alternativa, crie um método dinâmico alojado anonimamente com capacidade restrita para ignorar as verificações de visibilidade do JIT, utilizando o DynamicMethod(String, Type, Type[], Boolean) construtor e especificando
truepara orestrictedSkipVisibilityparâmetro .DynamicMethod meth = new DynamicMethod("", typeof(char), new Type[] { typeof(String) }, true);Dim meth As New DynamicMethod("", _ GetType(Char), _ New Type() {GetType(String)}, _ True)A restrição é que o método dinâmico alojado anonimamente só pode aceder a dados privados em assemblagens com níveis de confiança iguais ou inferiores ao nível de confiança da assemblagem emissora. Por exemplo, se o método dinâmico estiver a ser executado com a confiança da Internet, pode aceder a dados privados noutras assemblagens que também estão a ser executadas com confiança na Internet, mas não pode aceder a dados privados de assemblagens .NET Framework. .NET Framework assemblagens são instaladas na cache de assemblagem global e são sempre totalmente fidedignas.
Os métodos dinâmicos alojados anonimamente podem utilizar esta capacidade restrita para ignorar as verificações de visibilidade do JIT apenas se a aplicação anfitriã conceder ReflectionPermission com o ReflectionPermissionFlag.RestrictedMemberAccess sinalizador. A procura desta permissão é efetuada quando o método é invocado.
Nota
As informações da pilha de chamadas para a assemblagem emissora são incluídas quando o método dinâmico é construído. Por conseguinte, a exigência é feita contra as permissões da assemblagem emissora em vez da assemblagem que invoca o método . Isto impede que o código emitido seja executado com permissões elevadas.
O exemplo de código completo no final destas instruções demonstra a utilização e as limitações do acesso restrito aos membros. A sua
Workerclasse inclui um método que pode criar métodos dinâmicos alojados anonimamente com ou sem a capacidade restrita de ignorar verificações de visibilidade e o exemplo mostra o resultado da execução deste método em domínios de aplicações com diferentes níveis de confiança.Nota
A capacidade restrita de ignorar verificações de visibilidade é uma funcionalidade de métodos dinâmicos alojados anonimamente. Quando os métodos dinâmicos comuns ignoram as verificações de visibilidade do JIT, tem de lhes ser concedida confiança total.
Exemplo
Descrição
O exemplo de código seguinte demonstra a utilização do RestrictedMemberAccess sinalizador para permitir que os métodos dinâmicos alojados anonimamente ignorem as verificações de visibilidade do JIT, mas apenas quando o membro de destino está num nível de confiança igual ou inferior ao da assemblagem que emite o código.
O exemplo define uma Worker classe que pode ser ordenada através dos limites do domínio da aplicação. A classe tem duas AccessPrivateMethod sobrecargas de método que emitem e executam métodos dinâmicos. A primeira sobrecarga emite um método dinâmico que chama o método privado PrivateMethod da Worker classe e pode emitir o método dinâmico com ou sem verificações de visibilidade JIT. A segunda sobrecarga emite um método dinâmico que acede a uma internal propriedade (Friend propriedade no Visual Basic) da String classe .
O exemplo utiliza um método auxiliar para criar um conjunto de concessões limitado a Internet permissões e, em seguida, cria um domínio de aplicação, utilizando a sobrecarga do AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) método para especificar que todo o código que é executado no domínio utiliza este conjunto de concessões. O exemplo cria uma instância da Worker classe no domínio da aplicação e executa o AccessPrivateMethod método duas vezes.
Na primeira vez que o
AccessPrivateMethodmétodo é executado, as verificações de visibilidade do JIT são impostas. O método dinâmico falha quando é invocado, porque as verificações de visibilidade do JIT impedem que este aceda ao método privado.Na segunda vez que o
AccessPrivateMethodmétodo for executado, as verificações de visibilidade do JIT são ignoradas. O método dinâmico falha quando é compilado, porque oInternetconjunto de concessões não concede permissões suficientes para ignorar as verificações de visibilidade.
O exemplo adiciona ReflectionPermission com ReflectionPermissionFlag.RestrictedMemberAccess ao conjunto de concessões. Em seguida, o exemplo cria um segundo domínio, especificando que todo o código que é executado no domínio recebe as permissões no novo conjunto de concessões. O exemplo cria uma instância da Worker classe no novo domínio de aplicação e executa ambas as sobrecargas do AccessPrivateMethod método .
A primeira sobrecarga do
AccessPrivateMethodmétodo é executada e as verificações de visibilidade do JIT são ignoradas. O método dinâmico compila e é executado com êxito, porque a assemblagem que emite o código é a mesma que a assemblagem que contém o método privado. Portanto, os níveis de confiança são iguais. Se a aplicação que contém aWorkerclasse tivesse várias assemblagens, o mesmo processo seria bem-sucedido para qualquer uma dessas assemblagens, uma vez que todas estariam no mesmo nível de confiança.A segunda sobrecarga do
AccessPrivateMethodmétodo é executada e, novamente, as verificações de visibilidade do JIT são ignoradas. Desta vez, o método dinâmico falha quando é compilado, porque tenta aceder àinternalFirstCharpropriedade da String classe. A assemblagem que contém a String classe é totalmente fidedigna. Por conseguinte, está num nível de confiança mais elevado do que a assemblagem que emite o código.
Esta comparação mostra como ReflectionPermissionFlag.RestrictedMemberAccess permite que o código parcialmente fidedigno ignore as verificações de visibilidade de outro código parcialmente fidedigno sem comprometer a segurança do código fidedigno.
Código
using System;
using System.Reflection.Emit;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Collections;
using System.Diagnostics;
// This code example works properly only if it is run from a fully
// trusted location, such as your local computer.
// Delegates used to execute the dynamic methods.
//
public delegate void Test(Worker w);
public delegate void Test1();
public delegate char Test2(String instance);
// The Worker class must inherit MarshalByRefObject so that its public
// methods can be invoked across application domain boundaries.
//
public class Worker : MarshalByRefObject
{
private void PrivateMethod()
{
Console.WriteLine("Worker.PrivateMethod()");
}
public void SimpleEmitDemo()
{
DynamicMethod meth = new DynamicMethod("", null, null);
ILGenerator il = meth.GetILGenerator();
il.EmitWriteLine("Hello, World!");
il.Emit(OpCodes.Ret);
Test1 t1 = (Test1) meth.CreateDelegate(typeof(Test1));
t1();
}
// This overload of AccessPrivateMethod emits a dynamic method and
// specifies whether to skip JIT visiblity checks. It creates a
// delegate for the method and invokes the delegate. The dynamic
// method calls a private method of the Worker class.
public void AccessPrivateMethod(bool restrictedSkipVisibility)
{
// Create an unnamed dynamic method that has no return type,
// takes one parameter of type Worker, and optionally skips JIT
// visiblity checks.
DynamicMethod meth = new DynamicMethod(
"",
null,
new Type[] { typeof(Worker) },
restrictedSkipVisibility);
// Get a MethodInfo for the private method.
MethodInfo pvtMeth = typeof(Worker).GetMethod("PrivateMethod",
BindingFlags.NonPublic | BindingFlags.Instance);
// Get an ILGenerator and emit a body for the dynamic method.
ILGenerator il = meth.GetILGenerator();
// Load the first argument, which is the target instance, onto the
// execution stack, call the private method, and return.
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, pvtMeth, null);
il.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method, and
// invoke it.
try
{
Test t = (Test) meth.CreateDelegate(typeof(Test));
try
{
t(this);
}
catch (Exception ex)
{
Console.WriteLine("{0} was thrown when the delegate was invoked.",
ex.GetType().Name);
}
}
catch (Exception ex)
{
Console.WriteLine("{0} was thrown when the delegate was compiled.",
ex.GetType().Name);
}
}
// This overload of AccessPrivateMethod emits a dynamic method that takes
// a string and returns the first character, using a private field of the
// String class. The dynamic method skips JIT visiblity checks.
public void AccessPrivateMethod()
{
DynamicMethod meth = new DynamicMethod("",
typeof(char),
new Type[] { typeof(String) },
true);
// Get a MethodInfo for the 'get' accessor of the private property.
PropertyInfo pi = typeof(System.String).GetProperty(
"FirstChar",
BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo pvtMeth = pi.GetGetMethod(true);
// Get an ILGenerator and emit a body for the dynamic method.
ILGenerator il = meth.GetILGenerator();
// Load the first argument, which is the target string, onto the
// execution stack, call the 'get' accessor to put the result onto
// the execution stack, and return.
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, pvtMeth, null);
il.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method, and
// invoke it.
try
{
Test2 t = (Test2) meth.CreateDelegate(typeof(Test2));
char first = t("Hello, World!");
Console.WriteLine("{0} is the first character.", first);
}
catch (Exception ex)
{
Console.WriteLine("{0} was thrown when the delegate was compiled.",
ex.GetType().Name);
}
}
// The entry point for the code example.
static void Main()
{
// Get the display name of the executing assembly, to use when
// creating objects to run code in application domains.
String asmName = typeof(Worker).Assembly.FullName;
// Create the permission set to grant to other assemblies. In this
// case they are the permissions found in the Internet zone.
Evidence ev = new Evidence();
ev.AddHostEvidence(new Zone(SecurityZone.Internet));
PermissionSet pset = new NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev));
// For simplicity, set up the application domain to use the
// current path as the application folder, so the same executable
// can be used in both trusted and untrusted scenarios. Normally
// you would not do this with real untrusted code.
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = ".";
// Create an application domain in which all code that executes is
// granted the permissions of an application run from the Internet.
AppDomain ad = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, null);
// Create an instance of the Worker class in the partially trusted
// domain. Note: If you build this code example in Visual Studio,
// you must change the name of the class to include the default
// namespace, which is the project name. For example, if the project
// is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");
// Emit a simple dynamic method that prints "Hello, World!"
w.SimpleEmitDemo();
// Emit and invoke a dynamic method that calls a private method
// of Worker, with JIT visibility checks enforced. The call fails
// when the delegate is invoked.
w.AccessPrivateMethod(false);
// Emit and invoke a dynamic method that calls a private method
// of Worker, skipping JIT visibility checks. The call fails when
// the method is invoked.
w.AccessPrivateMethod(true);
// Unload the application domain. Add RestrictedMemberAccess to the
// grant set, and use it to create an application domain in which
// partially trusted code can call private members, as long as the
// trust level of those members is equal to or lower than the trust
// level of the partially trusted code.
AppDomain.Unload(ad);
pset.SetPermission(
new ReflectionPermission(
ReflectionPermissionFlag.RestrictedMemberAccess));
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);
// Create an instance of the Worker class in the partially trusted
// domain.
w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");
// Again, emit and invoke a dynamic method that calls a private method
// of Worker, skipping JIT visibility checks. This time compilation
// succeeds because of the grant for RestrictedMemberAccess.
w.AccessPrivateMethod(true);
// Finally, emit and invoke a dynamic method that calls an internal
// method of the String class. The call fails, because the trust level
// of the assembly that contains String is higher than the trust level
// of the assembly that emits the dynamic method.
w.AccessPrivateMethod();
}
}
/* This code example produces the following output:
Hello, World!
MethodAccessException was thrown when the delegate was invoked.
MethodAccessException was thrown when the delegate was invoked.
Worker.PrivateMethod()
MethodAccessException was thrown when the delegate was compiled.
*/
Imports System.Reflection.Emit
Imports System.Reflection
Imports System.Security
Imports System.Security.Permissions
Imports System.Security.Policy
Imports System.Collections
Imports System.Diagnostics
' This code example works properly only if it is run from a fully
' trusted location, such as your local computer.
' Delegates used to execute the dynamic methods.
'
Public Delegate Sub Test(ByVal w As Worker)
Public Delegate Sub Test1()
Public Delegate Function Test2(ByVal instance As String) As Char
' The Worker class must inherit MarshalByRefObject so that its public
' methods can be invoked across application domain boundaries.
'
Public Class Worker
Inherits MarshalByRefObject
Private Sub PrivateMethod()
Console.WriteLine("Worker.PrivateMethod()")
End Sub
Public Sub SimpleEmitDemo()
Dim meth As DynamicMethod = new DynamicMethod("", Nothing, Nothing)
Dim il As ILGenerator = meth.GetILGenerator()
il.EmitWriteLine("Hello, World!")
il.Emit(OpCodes.Ret)
Dim t1 As Test1 = CType(meth.CreateDelegate(GetType(Test1)), Test1)
t1()
End Sub
' This overload of AccessPrivateMethod emits a dynamic method and
' specifies whether to skip JIT visiblity checks. It creates a
' delegate for the method and invokes the delegate. The dynamic
' method calls a private method of the Worker class.
Overloads Public Sub AccessPrivateMethod( _
ByVal restrictedSkipVisibility As Boolean)
' Create an unnamed dynamic method that has no return type,
' takes one parameter of type Worker, and optionally skips JIT
' visiblity checks.
Dim meth As New DynamicMethod("", _
Nothing, _
New Type() {GetType(Worker)}, _
restrictedSkipVisibility)
' Get a MethodInfo for the private method.
Dim pvtMeth As MethodInfo = GetType(Worker).GetMethod( _
"PrivateMethod", _
BindingFlags.NonPublic Or BindingFlags.Instance)
' Get an ILGenerator and emit a body for the dynamic method.
Dim il As ILGenerator = meth.GetILGenerator()
' Load the first argument, which is the target instance, onto the
' execution stack, call the private method, and return.
il.Emit(OpCodes.Ldarg_0)
il.EmitCall(OpCodes.Call, pvtMeth, Nothing)
il.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method, and
' invoke it.
Try
Dim t As Test = CType(meth.CreateDelegate(GetType(Test)), Test)
Try
t(Me)
Catch ex As Exception
Console.WriteLine("{0} was thrown when the delegate was invoked.", _
ex.GetType().Name)
End Try
Catch ex As Exception
Console.WriteLine("{0} was thrown when the delegate was compiled.", _
ex.GetType().Name)
End Try
End Sub
' This overload of AccessPrivateMethod emits a dynamic method that takes
' a string and returns the first character, using a private field of the
' String class. The dynamic method skips JIT visiblity checks.
Overloads Public Sub AccessPrivateMethod()
Dim meth As New DynamicMethod("", _
GetType(Char), _
New Type() {GetType(String)}, _
True)
' Get a MethodInfo for the 'get' accessor of the private property.
Dim pi As PropertyInfo = GetType(String).GetProperty( _
"FirstChar", _
BindingFlags.NonPublic Or BindingFlags.Instance)
Dim pvtMeth As MethodInfo = pi.GetGetMethod(True)
' Get an ILGenerator and emit a body for the dynamic method.
Dim il As ILGenerator = meth.GetILGenerator()
' Load the first argument, which is the target string, onto the
' execution stack, call the 'get' accessor to put the result onto
' the execution stack, and return.
il.Emit(OpCodes.Ldarg_0)
il.EmitCall(OpCodes.Call, pvtMeth, Nothing)
il.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method, and
' invoke it.
Try
Dim t As Test2 = CType(meth.CreateDelegate(GetType(Test2)), Test2)
Dim first As Char = t("Hello, World!")
Console.WriteLine("{0} is the first character.", first)
Catch ex As Exception
Console.WriteLine("{0} was thrown when the delegate was compiled.", _
ex.GetType().Name)
End Try
End Sub
End Class
Friend Class Example
' The entry point for the code example.
Shared Sub Main()
' Get the display name of the executing assembly, to use when
' creating objects to run code in application domains.
Dim asmName As String = GetType(Worker).Assembly.FullName
' Create the permission set to grant to other assemblies. In this
' case they are the permissions found in the Internet zone.
Dim ev As New Evidence()
ev.AddHostEvidence(new Zone(SecurityZone.Internet))
Dim pset As New NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev))
' For simplicity, set up the application domain to use the
' current path as the application folder, so the same executable
' can be used in both trusted and untrusted scenarios. Normally
' you would not do this with real untrusted code.
Dim adSetup As New AppDomainSetup()
adSetup.ApplicationBase = "."
' Create an application domain in which all code that executes is
' granted the permissions of an application run from the Internet.
Dim ad As AppDomain = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, Nothing)
' Create an instance of the Worker class in the partially trusted
' domain. Note: If you build this code example in Visual Studio,
' you must change the name of the class to include the default
' namespace, which is the project name. For example, if the project
' is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
Dim w As Worker = _
CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)
' Emit a simple dynamic method that prints "Hello, World!"
w.SimpleEmitDemo()
' Emit and invoke a dynamic method that calls a private method
' of Worker, with JIT visibility checks enforced. The call fails
' when the delegate is invoked.
w.AccessPrivateMethod(False)
' Emit and invoke a dynamic method that calls a private method
' of Worker, skipping JIT visibility checks. The call fails when
' the method is compiled.
w.AccessPrivateMethod(True)
' Unload the application domain. Add RestrictedMemberAccess to the
' grant set, and use it to create an application domain in which
' partially trusted code can call private members, as long as the
' trust level of those members is equal to or lower than the trust
' level of the partially trusted code.
AppDomain.Unload(ad)
pset.SetPermission( _
New ReflectionPermission( _
ReflectionPermissionFlag.RestrictedMemberAccess))
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)
' Create an instance of the Worker class in the partially trusted
' domain.
w = CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)
' Again, emit and invoke a dynamic method that calls a private method
' of Worker, skipping JIT visibility checks. This time compilation
' succeeds because of the grant for RestrictedMemberAccess.
w.AccessPrivateMethod(True)
' Finally, emit and invoke a dynamic method that calls an internal
' method of the String class. The call fails, because the trust level
' of the assembly that contains String is higher than the trust level
' of the assembly that emits the dynamic method.
w.AccessPrivateMethod()
End Sub
End Class
' This code example produces the following output:
'
'Hello, World!
'MethodAccessException was thrown when the delegate was invoked.
'MethodAccessException was thrown when the delegate was invoked.
'Worker.PrivateMethod()
'MethodAccessException was thrown when the delegate was compiled.
'
A Compilar o Código
- Se criar este exemplo de código no Visual Studio, tem de alterar o nome da classe para incluir o espaço de nomes quando o CreateInstanceAndUnwrap transmitir ao método . Por predefinição, o espaço de nomes é o nome do projeto. Por exemplo, se o projeto for "PartialTrust", o nome da classe tem de ser "PartialTrust.Worker".