使用 Deny 方法
![]() |
---|
在 .NET Framework 4 版 中,已經移除對強制 Deny、RequestMinimum、RequestOptional 和 RequestRefuse 使用權限要求的執行階段支援。在依據 .NET Framework 4 (含) 以後版本為基礎的程式碼上不可以使用這些要求。如需這項變更和其他變更的詳細資訊,請參閱 .NET Framework 4 中的安全性變更。 |
呼叫 Deny 可避免存取拒絕的使用權限所指定的資源。 當您的程式碼呼叫 Deny 且下層呼叫端接著需求拒絕的使用權限,安全性檢查將會失敗,即使所有的呼叫端都擁有存取該資源的使用權限。 所需求的使用權限和拒絕的使用權限並無法完全使 Deny 產生作用,而所需求的使用權限並不需要是拒絕使用權限的子集。 然而,如果這兩個使用權限的交集為空 (即它們之間沒有共通的項目),對 Deny 的呼叫將不產生任何作用。 請注意,Deny 不能覆寫執行 Assert 的呼叫堆疊上較下層的程式碼。 如果呼叫堆疊中較下層的程式碼執行 Assert,那麼較下層的程式碼就能存取被呼叫堆疊中較上層程式碼拒絕的資源。
您可以在程式碼內使用呼叫 Deny 以自行保護,因為 Deny 無法使您的程式碼可用來存取拒絕的資源。 然而,對 Deny 的呼叫並不會中斷下層呼叫端的未來安全性判斷提示。
下圖將說明當使用 Deny 時所產生的影響。 假設以下有關組件 A、B、C、D 和 E 以及使用權限 P1 的陳述式為 True:
P1 表示讀取 C 磁碟機上所有檔案的權限
組件 A、B、C、D 和 E 已被授與 P1 使用權限
方法 F 在使用權限 P1 上放入一個需求
方法 C 會建立 P1 類別的執行個體,再呼叫 P1 的 Deny 方法
方法 A 包含於組件 A、方法 B 包含於組件 B 等等
使用拒絕
方法 C 對 Deny 的呼叫會影響 P1 需求的結果。 例如,假設方法 A 呼叫 B、B 呼叫 C、C 呼叫 E,而 E 呼叫 F。 因為方法 F 直接存取受 P1 保護的資源,所以方法 F 會呼叫 P1 的 Demand 方法 (或使用宣告式需求),為 P1 叫用一個安全性檢查。 這個需求會使執行階段從組件 E 開始,檢查呼叫堆疊中所有呼叫端的使用權限。 因為組件 E 已獲得 P1 使用權限,因此直接斷會繼續檢查組件 C 的使用權限。 但因為方法 C 已拒絕 P1,所以方法 E 所叫用的安全性檢查會失敗,且擲回 SecurityException。 它並不需注意到組件 C 和它的呼叫端 (組件 A 和 B) 是否已被授與 P1;安全性檢查仍將失敗。 因為方法 C 已呼叫 Deny,組件 A 和 B 內的程式碼即無法存取受 P1 保護的資源。
以下的範例將說明使用 Deny 方法以覆寫安全性檢查的宣告式語法。 在這個範例中,ReflectionPermission 語法指定兩個值:SecurityAction 列舉型別和 TypeInformation 屬性的設定值。 TypeInformation 設定為 True,表示這個權限是代表透過反映 (Reflection) 來檢視私用成員的權限,以及已經傳遞 SecurityAction.Deny 來拒絕該使用權限。 請參閱 ReflectionPermission 的說明以取得可指定值的完整清單。 使用這個安全性宣告時,方法將無法透過反映來讀取型別的私用成員。
Option Strict
Option Explicit
Imports System
Imports System.Security.Permissions
<ReflectionPermissionAttribute(SecurityAction.Deny, TypeInformation = true ")> Public Class
MyClass1
Public Sub New()
End Sub
Public Sub GetPublicMembers ()
' Access public members through reflection.
End Sub
End Class
using System;
using System.Security.Permissions;
[ReflectionPermissionAttribute(SecurityAction.Deny, TypeInformation = true)]
public class MyClass
{
public MyClass()
{
}
public void GetPublicMembers()
{
//Access public members through reflection.
}
}
以下的程式碼片段將說明使用 Deny 方法以覆寫安全性檢查的命令式語法。 在這個範例中,將會宣告一個 ReflectionPermission 物件,而 ReflectionPermissionFlag.TypeInformation 會傳遞給它的建構函式 (Constructor),以初始化目前的使用權限。 呼叫 Deny 方法時,絕不能使用該程式碼和呼叫端來透過反映讀取私用欄位。
Option Explicit
Option Strict
Imports System
Imports System.Security.Permissions
Public Class MyClass1
Public Sub New()
End Sub
Public Sub ReadRegistry()
Dim MyPermission As New ReflectionPermission (ReflectionPermissionFlag.TypeInformation)
MyPermission.Deny()
' Access public members through reflection.
End Sub
End Class
using System;
using System.Security.Permissions;
public class MyClass {
public MyClass() {
}
public void ReadRegistry() {
ReflectionPermission MyPermission = new ReflectionPermission (ReflectionPermissionFlag.TypeInformation);
MyPermission.Deny();
// Access public members through reflection.
}
}
使用 Deny 的標準化問題
拒絕 FileIOPermission、RegistryPermission、WebPermission、UrlIdentityPermission、SiteIdentityPermission 和 EnvironmentPermission 時,必須特別小心,因為單一檔案、登錄項目、URL 及系統路徑都可以使用多個名稱描述。 例如,單一檔案 MyFile.log 可以使用許多方式參考,包括 "c:\MyFile.log" 和 "\\MyMachineName\c$\MyFile.log"。 如果您建立表示存取 "c:\MyFile.log" 的使用權限,接著拒絕程式碼的該使用權限,則程式碼可能仍可使用替代路徑 "\\MyMachineName\c$\MyFile.log" 存取該檔案。
您可以使用 PermitOnly 和 Deny 的組合,以避免標準化的問題。 PermitOnly 讓您可以只指定資源的多個可能名稱中的一個,但是會有使用其他任何名稱都無法存取該資源的副作用 (Side Effect)。 在您使用 PermitOnly 為資源指定一個允許的名稱後,應該使用 Deny 來拒絕使用該名稱存取資源。
下列程式碼使用 Deny 和 PermitOnly 的組合,防止您的程式碼存取名為 MyLog.log 的資源。 這個程式碼也會封鎖使用所有替代名稱或路徑存取該資源的動作。
<FileIOPermissionAttribute(SecurityAction.PermitOnly, All := "C:\ "), FileIOPermissionAttribute(SecurityAction.Deny, All := "C:\MyLog.log")>
[FileIOPermissionAttribute(SecurityAction.PermitOnly, All = @"C:\ ")]
[FileIOPermissionAttribute(SecurityAction.Deny, All = @"C:\MyLog.log")]