Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Reflection emit menggunakan API yang sama dalam kondisi kepercayaan penuh atau sebagian, tetapi beberapa fitur memerlukan izin khusus dalam kode dengan kepercayaan sebagian. Selain itu, pancaran pantulan memiliki fitur, metode dinamis yang dihosting secara anonim, yang dirancang untuk digunakan dengan kepercayaan parsial dan oleh rakitan transparan keamanan.
Nota
Sebelum .NET Framework 3.5, diperlukan proses emisi kode dengan penanda ReflectionPermissionFlag.ReflectionEmit. Izin ini disertakan secara default dalam set izin yang bernama FullTrust
dan Intranet
, tetapi tidak dalam set izin Internet
. Oleh karena itu, pustaka dapat digunakan dengan kepercayaan parsial hanya jika memiliki atribut SecurityCriticalAttribute dan juga menjalankan metode Assert untuk ReflectionEmit. Pustaka tersebut memerlukan tinjauan keamanan yang cermat karena kesalahan pengodean dapat mengakibatkan lubang keamanan. .NET Framework 3.5 memungkinkan kode untuk dipancarkan dalam skenario kepercayaan parsial tanpa mengeluarkan tuntutan keamanan apa pun, karena menghasilkan kode secara inheren bukan operasi istimewa. Artinya, kode yang dihasilkan tidak memiliki lebih banyak izin daripada perakitan yang menerbitkannya. Ini memungkinkan perpustakaan yang menghasilkan kode memiliki transparansi keamanan dan menghilangkan kebutuhan akan ReflectionEmit, sehingga menulis perpustakaan yang aman tidak memerlukan tinjauan keamanan yang menyeluruh.
Panduan ini mengilustrasikan tugas-tugas berikut:
Menyiapkan kotak pasir sederhana untuk menguji sebagian kode tepercaya.
Penting
Ini adalah cara sederhana untuk bereksperimen dengan kode dalam kepercayaan parsial. Untuk menjalankan kode yang sebenarnya berasal dari lokasi yang tidak tepercaya, lihat Cara: Menjalankan Kode Tepercaya Sebagian di Kotak Pasir.
Menjalankan kode di domain aplikasi dengan kepercayaan parsial.
Untuk informasi selengkapnya tentang memancarkan kode dalam skenario kepercayaan parsial, lihat Masalah Keamanan di Reflection Emit.
Untuk daftar lengkap kode yang diperlihatkan dalam prosedur ini, lihat bagian Contoh di akhir panduan ini.
Menyiapkan Sebagian Lokasi Tepercaya
Dua prosedur berikut menunjukkan cara menyiapkan lokasi tempat Anda dapat menguji kode dengan kepercayaan parsial.
Prosedur pertama menunjukkan cara membuat domain aplikasi terkotakpasir tempat kode diberikan izin Internet.
Prosedur kedua menunjukkan cara menambahkan ReflectionPermission dengan flag ReflectionPermissionFlag.RestrictedMemberAccess ke domain aplikasi yang tepercaya sebagian, untuk memungkinkan akses ke data privat dalam rakitan dengan tingkat kepercayaan yang sama atau lebih rendah.
Membuat Domain Aplikasi Terisolasi
Untuk membuat domain aplikasi di mana assembly Anda berjalan dengan kepercayaan terbatas, Anda harus menentukan kumpulan izin yang akan diberikan ke assembly dengan menggunakan metode overload AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) untuk membuat domain aplikasi. Cara termudah untuk menentukan kumpulan izin adalah dengan mengambil set izin bernama dari kebijakan keamanan.
Prosedur berikut menciptakan domain aplikasi yang terkotak, menjalankan kode Anda dengan kepercayaan terbatas. Ini untuk menguji skenario di mana kode yang dihasilkan hanya dapat mengakses anggota publik dari tipe publik. Prosedur berikutnya menunjukkan cara menambahkan RestrictedMemberAccess, untuk menguji skenario di mana kode yang dihasilkan dapat mengakses tipe dan anggota yang tidak publik dalam rakitan yang diberikan izin yang sama atau lebih rendah.
Untuk membuat domain aplikasi dengan kepercayaan terbatas
Buat satu set izin untuk diberikan ke modul di domain aplikasi yang terisolasi. Pada kasus ini, set izin zona Internet digunakan.
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))
Buat objek AppDomainSetup untuk menginisialisasi domain aplikasi dengan jalur aplikasi.
Penting
Untuk kesederhanaan, contoh kode ini menggunakan folder saat ini. Untuk menjalankan kode yang sebenarnya berasal dari Internet, gunakan folder terpisah untuk kode yang tidak tepercaya, seperti yang dijelaskan dalam Cara: Menjalankan Kode Tepercaya Sebagian di Kotak Pasir.
AppDomainSetup adSetup = new AppDomainSetup(); adSetup.ApplicationBase = ".";
Dim adSetup As New AppDomainSetup() adSetup.ApplicationBase = "."
Buat domain aplikasi, tentukan informasi pengaturan domain aplikasi dan set hak akses untuk semua assembly yang berjalan di domain aplikasi.
AppDomain ad = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, null);
Dim ad As AppDomain = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, Nothing)
Parameter terakhir dari overload metode AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) memungkinkan Anda menentukan sekumpulan assembly yang akan diberikan kepercayaan penuh, bukan set izin dari domain aplikasi. Anda tidak perlu menentukan rakitan .NET Framework yang digunakan aplikasi Anda, karena rakitan tersebut berada di cache perakitan global. Rakitan di dalam Global Assembly Cache selalu dipercaya sepenuhnya. Anda dapat menggunakan parameter ini untuk menentukan assembly yang bernama kuat yang tidak ada di cache assembly global.
Menambahkan RestrictedMemberAccess ke Domain Terisolasi
Aplikasi host dapat memungkinkan metode dinamis yang dihosting secara anonim untuk memiliki akses ke data privat dalam rakitan yang memiliki tingkat kepercayaan sama dengan atau kurang dari tingkat kepercayaan rakitan yang memancarkan kode. Untuk mengaktifkan kemampuan terbatas dalam melewati pemeriksaan visibilitas just-in-time (JIT), aplikasi host menambahkan objek ReflectionPermission dengan flag ReflectionPermissionFlag.RestrictedMemberAccess (RMA) ke dalam set hak akses.
Misalnya, host mungkin memberikan izin aplikasi Internet dan RMA, sehingga aplikasi Internet dapat menghasilkan kode yang mengakses data privat dalam assembly-nya sendiri. Karena akses terbatas pada rakitan yang memiliki tingkat kepercayaan yang sama atau lebih rendah, aplikasi Internet tidak dapat mengakses anggota rakitan tepercaya sepenuhnya, seperti rakitan .NET Framework.
Nota
Untuk mencegah peningkatan hak istimewa, informasi tumpukan untuk assembly yang memancarkan disertakan ketika membangun metode dinamis yang dihosting secara anonim. Ketika metode dipanggil, informasi tumpukan diperiksa. Dengan demikian, metode dinamis yang di-host secara anonim yang dipanggil dari kode yang sepenuhnya tepercaya masih terbatas pada tingkat kepercayaan dari perakitan yang memancarkan.
Untuk membuat domain aplikasi dengan kepercayaan parsial ditambah RMA
Buat objek ReflectionPermission baru dengan bendera RestrictedMemberAccess (RMA), dan gunakan metode PermissionSet.SetPermission untuk menambahkan izin ke set pemberian.
pset.SetPermission( new ReflectionPermission( ReflectionPermissionFlag.RestrictedMemberAccess));
pset.SetPermission( _ New ReflectionPermission( _ ReflectionPermissionFlag.RestrictedMemberAccess))
Metode AddPermission akan menambahkan izin ke kumpulan izin jika belum termasuk. Jika izin sudah disertakan dalam set izin, tanda yang ditentukan akan ditambahkan ke izin yang ada.
Nota
RMA adalah fitur metode dinamis yang dihosting secara anonim. Ketika metode dinamis biasa melewati pemeriksaan visibilitas JIT, kode yang dihasilkan memerlukan kepercayaan penuh.
Buat domain aplikasi, tentukan informasi pengaturan domain aplikasi dan pengaturan izin.
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)
Menjalankan Kode di Domain Aplikasi Terisolasi
Prosedur berikut menjelaskan cara menentukan kelas dengan menggunakan metode yang dapat dijalankan di domain aplikasi, cara membuat instans kelas di domain, dan cara menjalankan metodenya.
Untuk menentukan dan menjalankan metode dalam domain aplikasi
Tentukan kelas yang berasal dari MarshalByRefObject. Ini memungkinkan Anda membuat instans kelas di domain aplikasi lain dan melakukan panggilan metode di seluruh batas domain aplikasi. Kelas dalam contoh ini diberi nama
Worker
.public class Worker : MarshalByRefObject {
Public Class Worker Inherits MarshalByRefObject
Tentukan metode publik yang berisi kode yang ingin Anda jalankan. Dalam contoh ini, kode memancarkan metode dinamis sederhana, membuat delegasi untuk menjalankan metode, dan memanggil delegasi.
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
Dalam program utama Anda, dapatkan nama tampilan dari assembly Anda. Nama ini digunakan saat Anda membuat instans kelas
Worker
di domain aplikasi terisolasi.String asmName = typeof(Worker).Assembly.FullName;
Dim asmName As String = GetType(Worker).Assembly.FullName
Dalam program utama Anda, buat domain aplikasi yang terlindungi, sesuai dengan prosedur pertama dalam panduan ini. Anda tidak perlu menambahkan izin apa pun ke kumpulan izin
Internet
, karena metodeSimpleEmitDemo
hanya menggunakan metode publik.Di program utama Anda, buat instans kelas
Worker
di domain aplikasi terisolasi.Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");
Dim w As Worker = _ CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)
Metode CreateInstanceAndUnwrap membuat objek di domain aplikasi target dan mengembalikan proksi yang dapat digunakan untuk memanggil properti dan metode objek.
Nota
Jika Anda menggunakan kode ini di Visual Studio, Anda harus mengubah nama kelas untuk menyertakan namespace. Secara default, namespace adalah nama proyek. Misalnya, jika proyek adalah "PartialTrust", nama kelas harus "PartialTrust.Worker".
Tambahkan kode untuk memanggil metode
SimpleEmitDemo
. Panggilan dikoordinasikan di seluruh batas domain aplikasi, dan kode dijalankan di domain aplikasi terproteksi.w.SimpleEmitDemo();
w.SimpleEmitDemo()
Menggunakan Metode Dinamis yang Dihosting Secara Anonim
Metode dinamis yang dihosting secara anonim dikaitkan dengan rakitan transparan yang disediakan oleh sistem. Oleh karena itu, kode yang dikandungnya transparan. Metode dinamis biasa, di sisi lain, harus dikaitkan dengan modul yang ada (baik yang ditentukan secara langsung atau disimpulkan dari jenis terkait), dan mengambil tingkat keamanannya dari modul tersebut.
Nota
Satu-satunya cara untuk mengaitkan metode dinamis dengan rakitan yang menyediakan hosting anonim adalah dengan menggunakan konstruktor yang dijelaskan dalam prosedur berikut. Anda tidak dapat secara eksplisit menentukan modul di rakitan hosting anonim.
Metode dinamis umum memiliki akses ke anggota internal dari modul yang berhubungan dengan mereka, atau ke anggota privat dari jenis yang berhubungan dengan mereka. Karena metode dinamis yang dihosting secara anonim diisolasi dari kode lain, mereka tidak memiliki akses ke data privat. Namun, mereka memang memiliki kemampuan terbatas untuk melewati pemeriksaan visibilitas JIT untuk mendapatkan akses ke data privat. Kemampuan ini terbatas pada rakitan yang memiliki tingkat kepercayaan sama dengan atau kurang dari tingkat kepercayaan rakitan yang memancarkan kode.
Untuk mencegah peningkatan hak istimewa, informasi tumpukan untuk assembly yang memancarkan disertakan ketika membangun metode dinamis yang dihosting secara anonim. Ketika metode dipanggil, informasi tumpukan diperiksa. Metode dinamis yang dihosting secara anonim yang dipanggil dari kode yang sepenuhnya dipercaya masih terbatas pada tingkat kepercayaan rakitan yang memancarkannya.
Untuk menggunakan metode dinamis yang dihosting secara anonim
Buat metode dinamis yang dihosting secara anonim dengan menggunakan konstruktor yang tidak menentukan modul atau jenis terkait.
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)
Jika metode dinamis yang dihosting secara anonim hanya menggunakan jenis dan metode publik, metode tersebut tidak memerlukan akses anggota terbatas dan tidak harus melewati pemeriksaan visibilitas JIT.
Tidak ada izin khusus yang diperlukan untuk memancarkan metode dinamis, tetapi kode yang dipancarkan memerlukan izin yang diminta oleh jenis dan metode yang digunakannya. Misalnya, jika kode yang dipancarkan memanggil metode yang mengakses file, kode tersebut memerlukan FileIOPermission. Jika tingkat kepercayaan tidak menyertakan izin tersebut, pengecualian keamanan akan dilemparkan saat kode yang dipancarkan dijalankan. Kode yang ditampilkan di sini memancarkan metode dinamis yang hanya menggunakan metode Console.WriteLine. Oleh karena itu, kode dapat dijalankan dari lokasi tepercaya sebagian.
Atau, buat metode dinamis yang dihosting secara anonim dengan kemampuan terbatas untuk melewati pemeriksaan visibilitas JIT, dengan menggunakan konstruktor DynamicMethod(String, Type, Type[], Boolean) dan menentukan
true
untuk parameterrestrictedSkipVisibility
.DynamicMethod meth = new DynamicMethod("", typeof(char), new Type[] { typeof(String) }, true);
Dim meth As New DynamicMethod("", _ GetType(Char), _ New Type() {GetType(String)}, _ True)
Pembatasannya adalah bahwa metode dinamis yang dihosting secara anonim hanya dapat mengakses data privat dalam rakitan dengan tingkat kepercayaan yang sama atau lebih rendah dari tingkat kepercayaan rakitan yang mengemisi. Misalnya, jika metode dinamis dijalankan dengan kepercayaan Internet, metode ini dapat mengakses data privat di rakitan lain yang juga dijalankan dengan kepercayaan Internet, tetapi tidak dapat mengakses data privat rakitan .NET Framework. Assembly .NET Framework dipasang di cache assembly global dan selalu sepenuhnya terpercaya.
Metode dinamis yang dihosting secara anonim dapat menggunakan kemampuan terbatas ini untuk melewati pemeriksaan visibilitas JIT hanya jika aplikasi host memberikan ReflectionPermission dengan bendera ReflectionPermissionFlag.RestrictedMemberAccess. Permintaan untuk izin ini dibuat ketika metode dipanggil.
Nota
Informasi tumpukan panggilan untuk assembly pemancar disertakan saat metode dinamis dikonstruksi. Oleh karena itu, permintaan dibuat terhadap izin assembly pemancar, bukan perakitan yang memanggil metode. Ini mencegah kode yang dihasilkan dijalankan dengan hak istimewa yang lebih tinggi.
Contoh kode lengkap di akhir panduan ini menunjukkan penggunaan dan batasan akses anggota terbatas. Kelas
Worker
mencakup metode yang dapat membuat metode dinamis yang dihosting secara anonim dengan atau tanpa kemampuan terbatas untuk melewati pemeriksaan visibilitas, dan contoh menunjukkan hasil menjalankan metode ini di domain aplikasi yang memiliki tingkat kepercayaan yang berbeda.Nota
Kemampuan terbatas untuk melewati pemeriksaan visibilitas adalah fitur metode dinamis yang dihosting secara anonim. Ketika metode dinamis biasa melewatkan pemeriksaan visibilitas JIT, metode tersebut harus diberikan tingkat kepercayaan penuh.
Contoh
Deskripsi
Contoh kode berikut menunjukkan penggunaan bendera RestrictedMemberAccess untuk memungkinkan metode dinamis yang dihosting secara anonim untuk melewati pemeriksaan visibilitas JIT, tetapi hanya ketika anggota target berada pada tingkat kepercayaan yang sama atau lebih rendah daripada rakitan yang memancarkan kode.
Contohnya mendefinisikan kelas Worker
yang dapat dinaikkan di seluruh batas domain aplikasi. Kelas ini memiliki dua overload metode AccessPrivateMethod
yang menghasilkan dan menjalankan metode dinamis. Overload pertama memancarkan metode dinamis yang memanggil metode privat PrivateMethod
dari kelas Worker
, dan dapat memancarkan metode dinamis dengan atau tanpa pemeriksaan visibilitas JIT. Kelebihan beban kedua memancarkan metode dinamis yang mengakses properti internal
( propertiFriend
di Visual Basic) dari kelas String.
Contoh ini menggunakan metode pembantu untuk membuat set hak akses yang terbatas pada izin Internet
, lalu membuat domain aplikasi, menggunakan overload metode AppDomain.CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[]) untuk menentukan bahwa semua kode yang dieksekusi di domain ini menggunakan set hak akses tersebut. Contohnya membuat instans kelas Worker
di domain aplikasi, dan menjalankan metode AccessPrivateMethod
dua kali.
Pertama kali metode
AccessPrivateMethod
dijalankan, pemeriksaan visibilitas JIT diberlakukan. Metode dinamis gagal ketika dipanggil, karena pemeriksaan visibilitas JIT mencegahnya mengakses metode privat.Pada kali kedua metode
AccessPrivateMethod
dijalankan, pemeriksaan visibilitas JIT diabaikan. Metode dinamis gagal ketika dikompilasi, karena kumpulan izinInternet
tidak memberikan cukup izin untuk melewati pemeriksaan visibilitas.
Contoh menambahkan ReflectionPermission dengan ReflectionPermissionFlag.RestrictedMemberAccess ke kumpulan hibah. Contoh kemudian membuat domain kedua, menentukan bahwa semua kode yang dieksekusi dalam domain diberikan izin pada set izin yang baru. Contoh membuat instans kelas Worker
di domain aplikasi baru, dan menjalankan kedua kelebihan beban metode AccessPrivateMethod
.
Overload pertama dari metode
AccessPrivateMethod
dijalankan, dan pemeriksaan visibilitas JIT dilewati. Metode dinamis berhasil mengkompilasi dan menjalankan, karena rakitan yang memancarkan kode sama dengan rakitan yang berisi metode privat. Oleh karena itu, tingkat kepercayaan sama. Jika aplikasi yang berisi kelasWorker
memiliki beberapa rakitan, proses yang sama akan berhasil untuk salah satu rakitan tersebut, karena semuanya akan berada di tingkat kepercayaan yang sama.Kelebihan beban kedua dari metode
AccessPrivateMethod
dijalankan, dan sekali lagi pemeriksaan visibilitas JIT dilewati. Kali ini metode dinamis gagal ketika dikompilasi, karena mencoba mengakses propertiinternal
FirstChar
kelas String. Perakitan yang berisi kelas String dapat dipercaya sepenuhnya. Oleh karena itu, berada pada tingkat kepercayaan yang lebih tinggi daripada rakitan yang memancarkan kode.
Perbandingan ini menunjukkan bagaimana ReflectionPermissionFlag.RestrictedMemberAccess memungkinkan kode tepercaya sebagian untuk melewati pemeriksaan visibilitas untuk kode tepercaya parsial lainnya tanpa mengorbankan keamanan kode tepercaya.
Kode
using System;
using System.Reflection.Emit;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Collections;
using System.Diagnostics;
// This code example works properly only if it is run from a fully
// trusted location, such as your local computer.
// Delegates used to execute the dynamic methods.
//
public delegate void Test(Worker w);
public delegate void Test1();
public delegate char Test2(String instance);
// The Worker class must inherit MarshalByRefObject so that its public
// methods can be invoked across application domain boundaries.
//
public class Worker : MarshalByRefObject
{
private void PrivateMethod()
{
Console.WriteLine("Worker.PrivateMethod()");
}
public void SimpleEmitDemo()
{
DynamicMethod meth = new DynamicMethod("", null, null);
ILGenerator il = meth.GetILGenerator();
il.EmitWriteLine("Hello, World!");
il.Emit(OpCodes.Ret);
Test1 t1 = (Test1) meth.CreateDelegate(typeof(Test1));
t1();
}
// This overload of AccessPrivateMethod emits a dynamic method and
// specifies whether to skip JIT visiblity checks. It creates a
// delegate for the method and invokes the delegate. The dynamic
// method calls a private method of the Worker class.
public void AccessPrivateMethod(bool restrictedSkipVisibility)
{
// Create an unnamed dynamic method that has no return type,
// takes one parameter of type Worker, and optionally skips JIT
// visiblity checks.
DynamicMethod meth = new DynamicMethod(
"",
null,
new Type[] { typeof(Worker) },
restrictedSkipVisibility);
// Get a MethodInfo for the private method.
MethodInfo pvtMeth = typeof(Worker).GetMethod("PrivateMethod",
BindingFlags.NonPublic | BindingFlags.Instance);
// Get an ILGenerator and emit a body for the dynamic method.
ILGenerator il = meth.GetILGenerator();
// Load the first argument, which is the target instance, onto the
// execution stack, call the private method, and return.
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, pvtMeth, null);
il.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method, and
// invoke it.
try
{
Test t = (Test) meth.CreateDelegate(typeof(Test));
try
{
t(this);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType().Name} was thrown when the delegate was invoked.");
}
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType().Name} was thrown when the delegate was compiled.");
}
}
// This overload of AccessPrivateMethod emits a dynamic method that takes
// a string and returns the first character, using a private field of the
// String class. The dynamic method skips JIT visiblity checks.
public void AccessPrivateMethod()
{
DynamicMethod meth = new DynamicMethod("",
typeof(char),
new Type[] { typeof(String) },
true);
// Get a MethodInfo for the 'get' accessor of the private property.
PropertyInfo pi = typeof(System.String).GetProperty(
"FirstChar",
BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo pvtMeth = pi.GetGetMethod(true);
// Get an ILGenerator and emit a body for the dynamic method.
ILGenerator il = meth.GetILGenerator();
// Load the first argument, which is the target string, onto the
// execution stack, call the 'get' accessor to put the result onto
// the execution stack, and return.
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, pvtMeth, null);
il.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method, and
// invoke it.
try
{
Test2 t = (Test2) meth.CreateDelegate(typeof(Test2));
char first = t("Hello, World!");
Console.WriteLine($"{first} is the first character.");
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType().Name} was thrown when the delegate was compiled.");
}
}
// The entry point for the code example.
static void Main()
{
// Get the display name of the executing assembly, to use when
// creating objects to run code in application domains.
String asmName = typeof(Worker).Assembly.FullName;
// Create the permission set to grant to other assemblies. In this
// case they are the permissions found in the Internet zone.
Evidence ev = new Evidence();
ev.AddHostEvidence(new Zone(SecurityZone.Internet));
PermissionSet pset = new NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev));
// For simplicity, set up the application domain to use the
// current path as the application folder, so the same executable
// can be used in both trusted and untrusted scenarios. Normally
// you would not do this with real untrusted code.
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = ".";
// Create an application domain in which all code that executes is
// granted the permissions of an application run from the Internet.
AppDomain ad = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, null);
// Create an instance of the Worker class in the partially trusted
// domain. Note: If you build this code example in Visual Studio,
// you must change the name of the class to include the default
// namespace, which is the project name. For example, if the project
// is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
Worker w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");
// Emit a simple dynamic method that prints "Hello, World!"
w.SimpleEmitDemo();
// Emit and invoke a dynamic method that calls a private method
// of Worker, with JIT visibility checks enforced. The call fails
// when the delegate is invoked.
w.AccessPrivateMethod(false);
// Emit and invoke a dynamic method that calls a private method
// of Worker, skipping JIT visibility checks. The call fails when
// the method is invoked.
w.AccessPrivateMethod(true);
// Unload the application domain. Add RestrictedMemberAccess to the
// grant set, and use it to create an application domain in which
// partially trusted code can call private members, as long as the
// trust level of those members is equal to or lower than the trust
// level of the partially trusted code.
AppDomain.Unload(ad);
pset.SetPermission(
new ReflectionPermission(
ReflectionPermissionFlag.RestrictedMemberAccess));
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, null);
// Create an instance of the Worker class in the partially trusted
// domain.
w = (Worker) ad.CreateInstanceAndUnwrap(asmName, "Worker");
// Again, emit and invoke a dynamic method that calls a private method
// of Worker, skipping JIT visibility checks. This time compilation
// succeeds because of the grant for RestrictedMemberAccess.
w.AccessPrivateMethod(true);
// Finally, emit and invoke a dynamic method that calls an internal
// method of the String class. The call fails, because the trust level
// of the assembly that contains String is higher than the trust level
// of the assembly that emits the dynamic method.
w.AccessPrivateMethod();
}
}
/* This code example produces the following output:
Hello, World!
MethodAccessException was thrown when the delegate was invoked.
MethodAccessException was thrown when the delegate was invoked.
Worker.PrivateMethod()
MethodAccessException was thrown when the delegate was compiled.
*/
Imports System.Reflection.Emit
Imports System.Reflection
Imports System.Security
Imports System.Security.Permissions
Imports System.Security.Policy
Imports System.Collections
Imports System.Diagnostics
' This code example works properly only if it is run from a fully
' trusted location, such as your local computer.
' Delegates used to execute the dynamic methods.
'
Public Delegate Sub Test(ByVal w As Worker)
Public Delegate Sub Test1()
Public Delegate Function Test2(ByVal instance As String) As Char
' The Worker class must inherit MarshalByRefObject so that its public
' methods can be invoked across application domain boundaries.
'
Public Class Worker
Inherits MarshalByRefObject
Private Sub PrivateMethod()
Console.WriteLine("Worker.PrivateMethod()")
End Sub
Public Sub SimpleEmitDemo()
Dim meth As DynamicMethod = new DynamicMethod("", Nothing, Nothing)
Dim il As ILGenerator = meth.GetILGenerator()
il.EmitWriteLine("Hello, World!")
il.Emit(OpCodes.Ret)
Dim t1 As Test1 = CType(meth.CreateDelegate(GetType(Test1)), Test1)
t1()
End Sub
' This overload of AccessPrivateMethod emits a dynamic method and
' specifies whether to skip JIT visiblity checks. It creates a
' delegate for the method and invokes the delegate. The dynamic
' method calls a private method of the Worker class.
Overloads Public Sub AccessPrivateMethod( _
ByVal restrictedSkipVisibility As Boolean)
' Create an unnamed dynamic method that has no return type,
' takes one parameter of type Worker, and optionally skips JIT
' visiblity checks.
Dim meth As New DynamicMethod("", _
Nothing, _
New Type() {GetType(Worker)}, _
restrictedSkipVisibility)
' Get a MethodInfo for the private method.
Dim pvtMeth As MethodInfo = GetType(Worker).GetMethod( _
"PrivateMethod", _
BindingFlags.NonPublic Or BindingFlags.Instance)
' Get an ILGenerator and emit a body for the dynamic method.
Dim il As ILGenerator = meth.GetILGenerator()
' Load the first argument, which is the target instance, onto the
' execution stack, call the private method, and return.
il.Emit(OpCodes.Ldarg_0)
il.EmitCall(OpCodes.Call, pvtMeth, Nothing)
il.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method, and
' invoke it.
Try
Dim t As Test = CType(meth.CreateDelegate(GetType(Test)), Test)
Try
t(Me)
Catch ex As Exception
Console.WriteLine("{0} was thrown when the delegate was invoked.", _
ex.GetType().Name)
End Try
Catch ex As Exception
Console.WriteLine("{0} was thrown when the delegate was compiled.", _
ex.GetType().Name)
End Try
End Sub
' This overload of AccessPrivateMethod emits a dynamic method that takes
' a string and returns the first character, using a private field of the
' String class. The dynamic method skips JIT visiblity checks.
Overloads Public Sub AccessPrivateMethod()
Dim meth As New DynamicMethod("", _
GetType(Char), _
New Type() {GetType(String)}, _
True)
' Get a MethodInfo for the 'get' accessor of the private property.
Dim pi As PropertyInfo = GetType(String).GetProperty( _
"FirstChar", _
BindingFlags.NonPublic Or BindingFlags.Instance)
Dim pvtMeth As MethodInfo = pi.GetGetMethod(True)
' Get an ILGenerator and emit a body for the dynamic method.
Dim il As ILGenerator = meth.GetILGenerator()
' Load the first argument, which is the target string, onto the
' execution stack, call the 'get' accessor to put the result onto
' the execution stack, and return.
il.Emit(OpCodes.Ldarg_0)
il.EmitCall(OpCodes.Call, pvtMeth, Nothing)
il.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method, and
' invoke it.
Try
Dim t As Test2 = CType(meth.CreateDelegate(GetType(Test2)), Test2)
Dim first As Char = t("Hello, World!")
Console.WriteLine("{0} is the first character.", first)
Catch ex As Exception
Console.WriteLine("{0} was thrown when the delegate was compiled.", _
ex.GetType().Name)
End Try
End Sub
End Class
Friend Class Example
' The entry point for the code example.
Shared Sub Main()
' Get the display name of the executing assembly, to use when
' creating objects to run code in application domains.
Dim asmName As String = GetType(Worker).Assembly.FullName
' Create the permission set to grant to other assemblies. In this
' case they are the permissions found in the Internet zone.
Dim ev As New Evidence()
ev.AddHostEvidence(new Zone(SecurityZone.Internet))
Dim pset As New NamedPermissionSet("Internet", SecurityManager.GetStandardSandbox(ev))
' For simplicity, set up the application domain to use the
' current path as the application folder, so the same executable
' can be used in both trusted and untrusted scenarios. Normally
' you would not do this with real untrusted code.
Dim adSetup As New AppDomainSetup()
adSetup.ApplicationBase = "."
' Create an application domain in which all code that executes is
' granted the permissions of an application run from the Internet.
Dim ad As AppDomain = AppDomain.CreateDomain("Sandbox", ev, adSetup, pset, Nothing)
' Create an instance of the Worker class in the partially trusted
' domain. Note: If you build this code example in Visual Studio,
' you must change the name of the class to include the default
' namespace, which is the project name. For example, if the project
' is "AnonymouslyHosted", the class is "AnonymouslyHosted.Worker".
Dim w As Worker = _
CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)
' Emit a simple dynamic method that prints "Hello, World!"
w.SimpleEmitDemo()
' Emit and invoke a dynamic method that calls a private method
' of Worker, with JIT visibility checks enforced. The call fails
' when the delegate is invoked.
w.AccessPrivateMethod(False)
' Emit and invoke a dynamic method that calls a private method
' of Worker, skipping JIT visibility checks. The call fails when
' the method is compiled.
w.AccessPrivateMethod(True)
' Unload the application domain. Add RestrictedMemberAccess to the
' grant set, and use it to create an application domain in which
' partially trusted code can call private members, as long as the
' trust level of those members is equal to or lower than the trust
' level of the partially trusted code.
AppDomain.Unload(ad)
pset.SetPermission( _
New ReflectionPermission( _
ReflectionPermissionFlag.RestrictedMemberAccess))
ad = AppDomain.CreateDomain("Sandbox2", ev, adSetup, pset, Nothing)
' Create an instance of the Worker class in the partially trusted
' domain.
w = CType(ad.CreateInstanceAndUnwrap(asmName, "Worker"), Worker)
' Again, emit and invoke a dynamic method that calls a private method
' of Worker, skipping JIT visibility checks. This time compilation
' succeeds because of the grant for RestrictedMemberAccess.
w.AccessPrivateMethod(True)
' Finally, emit and invoke a dynamic method that calls an internal
' method of the String class. The call fails, because the trust level
' of the assembly that contains String is higher than the trust level
' of the assembly that emits the dynamic method.
w.AccessPrivateMethod()
End Sub
End Class
' This code example produces the following output:
'
'Hello, World!
'MethodAccessException was thrown when the delegate was invoked.
'MethodAccessException was thrown when the delegate was invoked.
'Worker.PrivateMethod()
'MethodAccessException was thrown when the delegate was compiled.
'
Mengkompilasi Kode
- Jika Anda membuat contoh kode ini di Visual Studio, Anda harus mengubah nama kelas untuk menyertakan namespace saat Anda meneruskannya ke metode CreateInstanceAndUnwrap. Secara default, namespace adalah nama proyek. Misalnya, jika proyek adalah "PartialTrust", nama kelas harus "PartialTrust.Worker".