共用方式為


反映發出中的安全性問題

.NET Framework 提供三種發出 Microsoft Intermediate Language (MSIL) 的方式,每一種方式本身都有安全性問題:

  • 動態組件

  • 匿名裝載動態方法

  • 與現有組件關聯的動態方法

無論您使用哪種方法產生動態程式碼,在執行產生的程式碼時都需要產生之程式碼使用的型別和方法所需的使用權限。

注意事項注意事項

反映程式碼和發出程式碼所需的使用權限在 .NET Framework 的後續版本中已變更。請參閱本主題稍後提及的版本資訊。

動態組件

動態組件是使用 AppDomain.DefineDynamicAssembly 方法的多載所建立, 在 .NET Framework 4 版 中,因為全機器的安全性原則已不存在,所以這個方法的大多數多載都已被取代。 (請參閱 .NET Framework 4 中的安全性變更)。其餘的多載則可由任何程式碼 (無論程式碼的信任層級為何) 執行。 這些多載可分為兩類:一類會指定屬性清單,來指定當建立動態組件時要套用至該動態組件的屬性;另一類則不會。 如果您建立組件時未套用 SecurityRulesAttribute 屬性以指定該組件的透明度模型,則會從發出組件繼承透明度模型。

注意事項注意事項

您在動態組件建立後使用 SetCustomAttribute 方法套用至該動態組件的屬性,要等到將該組件儲存至磁碟並重新載入至記憶體後才會生效。

動態組件內的程式碼可以存取其他組件內的可見型別和成員。

注意事項注意事項

動態組件不會使用 ReflectionPermissionFlag.MemberAccessReflectionPermissionFlag.RestrictedMemberAccess 旗標來允許動態方法存取非公用的型別和成員。

暫時性 (Transient) 的動態組件會在記憶體內建立,而且永遠不會儲存到磁碟中,因此不需要檔案存取權限。 將動態組件儲存至磁碟需要具有適當旗標的 FileIOPermission

從部分信任的程式碼產生動態組件

請考慮某種情況,具有網際網路使用權限的組件可以產生暫時性動態組件並執行其程式碼:

  • 動態組件只會使用其他組件的公用型別和成員。

  • 由那些型別和成員要求的使用權限包含在部分信任組件的授權集中。

  • 組件不會儲存至磁碟。

  • 不會產生偵錯符號 (Internet 和 LocalIntranet 使用權限集不會包含必要的使用權限)。

匿名裝載動態方法

匿名裝載動態方法是使用兩種沒有指定相關聯型別或模組的 DynamicMethod 建構函式 (即 DynamicMethod(String, Type, Type[]) 和 DynamicMethod(String, Type, Type[], Boolean)) 來建立。 這些建構函式會將動態方法置放在一個系統提供、完全受信任、安全性透明的組件中。 使用這些建構函式或使用動態方法的發出程式碼時,不需要任何使用權限。

建立匿名裝載動態方法時,會改為擷取呼叫堆疊。 建構方法時,會針對已擷取的呼叫堆疊產生安全性要求。

注意事項注意事項

在概念上來說,這些要求是在方法建構期間產生的。那表示,這些要求可以在發出每個 MSIL 指令時產生。在目前的實作中,如果叫用方法時未呼叫 CreateDelegate,則所有的要求都會在呼叫 DynamicMethod.CreateDelegate 方法時產生,或在叫用 Just-In-Time (JIT) 編譯器時產生。

如果應用程式定義域允許的話,匿名裝載動態方法可以略過 JIT 可視性檢查,但有下列限制:由匿名裝載動態方法存取之非公用型別和成員的所在組件,其授權集必須與發出呼叫堆疊的授權集相等或者是其子集。 如果應用程式定義域授與具有 ReflectionPermissionFlag.RestrictedMemberAccess 旗標的 ReflectionPermission,即會啟用這項在略過 JIT 可視性檢查方面的限制。

  • 如果您的方法只會使用公用型別和成員,則在建構期間不需要使用權限。

  • 如果您指定應該略過 JIT 可視性檢查,則在建構方法時,所產生的要求包括內含 ReflectionPermissionFlag.RestrictedMemberAccess 旗標的 ReflectionPermission,以及包含正在存取非 Public 成員之組件的授權集。

由於已將非 Public 成員的授權集納入考量,已授與 ReflectionPermissionFlag.RestrictedMemberAccess 的部分信任程式碼將無法藉由執行受信任組件的非 Public 成員來提高其權限。

跟任何其他發出的程式碼一樣,執行動態方法所需的使用權限都會由動態方法使用的方法發出要求。

裝載匿名裝載動態方法的系統組件會使用 SecurityRuleSet.Level1 透明度模型,也就是在 .NET Framework 4 之前的 .NET Framework 版本中使用的透明度模型。

如需詳細資訊,請參閱 DynamicMethod 類別。

從部分信任程式碼產生匿名裝載動態方法

請考慮某種情況,具有網際網路使用權限的組件可以產生匿名裝載動態方法並執行該方法:

  • 動態方法只會使用公用型別和成員。 如果其授權集包含 ReflectionPermissionFlag.RestrictedMemberAccess,則可以使用與發出組件之授權集相等的任何組件之非公用型別和成員,或發出組件之授權集的子集。

  • 由動態方法使用的所有型別和成員要求的使用權限會包含在部分信任組件的授權集中。

注意事項注意事項

動態方法不支援偵錯符號。

與現有組件關聯的動態方法

若要讓動態方法與現有組件內的型別或模組產生關聯,請使用任何一個指定關聯型別或模組的 DynamicMethod 建構函式來進行。 呼叫這些建構函式時的必要使用權限有所不同,因為將動態方法與現有型別或模組產生關聯會提供存取非公用型別和成員的動態方法:

  • 與型別相關聯的動態方法可存取該型別的所有成員 (甚至是 Private 成員),以及存取包含相關聯型別之組件的所有 Internal 型別和成員。

  • 與模組相關聯的動態方法可以存取模組內所有 internal 型別和成員 (在 Visual Basic 內則為 Friend,在 Common Language Runtime 中繼資料內則為 assembly)。

此外,您可以使用指定要略過 JIT 編譯器之可視性檢查的建構函式。 這麼做可讓您的動態方法存取所有組件內的所有型別和成員,不管其存取層級為何。

建構函式要求的使用權限需視您決定給予讓動態方法的存取層級而定:

雖然此清單內的項目是從發出組件的授權集觀點來描述,不過請記住,這些要求是針對完整的呼叫堆疊而產生的,包括應用程式定義域界限。

如需詳細資訊,請參閱 DynamicMethod 類別。

從部分信任的程式碼產生動態方法

注意事項注意事項

從部分信任的程式碼產生動態方法的建議方式,是使用匿名裝載動態方法來進行。

請考慮某種情況,具有網際網路使用權限的組件可以產生動態方法並執行該方法:

  • 動態方法會與其發出的模組或型別產生關聯,或者其授權集會包含 ReflectionPermissionFlag.RestrictedMemberAccess,且會在與發出組件授權集相等之組件內的模組產生關聯,或與發出組件授權集的子集產生關聯。

  • 動態方法只會使用公用型別和成員。 如果其授權集包含 ReflectionPermissionFlag.RestrictedMemberAccess,且其與和發出組件之授權集相等的組件內模組產生關聯,或者和發出組件之授權集的子集產生關聯,則可以使用關聯模組內標記為 internal (在 Visual Basic 內為 Friend,在 Common Language Runtime 中繼資料內為 assembly) 的型別和成員。

  • 由動態方法使用的所有型別和成員要求的使用權限會包含在部分信任組件的授權集中。

  • 動態方法不會略過 JIT 可視性檢查。

注意事項注意事項

動態方法不支援偵錯符號。

版本資訊

自 .NET Framework 4 開始,全機器安全性原則已不再存在,安全性透明度將會成為預設的強制機制。 請參閱 .NET Framework 4 中的安全性變更

從 .NET Framework 2.0 版 Service Pack 1 開始,在發出動態組件和動態方法時,不再需要含 ReflectionPermissionFlag.ReflectionEmit 旗標的 ReflectionPermission。 在所有舊版的 .NET Framework 中則需要使用這個旗標。

注意事項注意事項

ReflectionPermissionFlag.ReflectionEmit 旗標的 ReflectionPermission 預設會包含在 FullTrust 和 LocalIntranet 具名使用權限集合中,而非 Internet 使用權限集中。因此,在舊版 .NET Framework 中,只有當程式庫執行 ReflectionEmitAssert 時,才可以透過網際網路使用權限來使用該程式庫。這類程式庫需要經審慎的安全性檢閱,因為程式碼錯誤可能會產生安全性漏洞。.NET Framework 2.0 SP1 允許程式碼在部分信任案例中發出,而且不發出任何安全性要求,因為產生程式碼本身並非特殊權限操作。也就是說,產生的程式碼不會有比發出它的組件更大的使用權限。這會允許發出程式碼的程式庫成為安全性透明,而無須判斷提示 (Assert) ReflectionEmit,如此可簡化撰寫安全程式庫的工作。

此外,.NET Framework 2.0 SP1 還新增 ReflectionPermissionFlag.RestrictedMemberAccess 旗標,以便從部分信任的動態方法中存取非公用型別和成員。 舊版的 .NET Framework 需要 ReflectionPermissionFlag.MemberAccess 旗標,才能讓動態方法存取非公用型別和成員,這是一種永遠都不應該授與部分信任程式碼的使用權限。

最後,.NET Framework 2.0 SP1 加入了匿名裝載方法。

取得型別和成員的資訊

從 .NET Framework 2.0 開始,在取得與非公用型別和成員相關的資訊時,已不需要使用權限。 反映 (Reflection) 可用於取得發出動態方法所需的資訊。 例如,MethodInfo 物件可用來發出方法呼叫。 舊版 .NET Framework 需要具有含 ReflectionPermissionFlag.TypeInformation 旗標的 ReflectionPermission。 如需詳細資訊,請參閱 反映的安全性考量

請參閱

概念

反映的安全性考量

其他資源

發出動態方法和組件