重要的安全性概念
.NET 提供以角色為基礎的安全性,以幫助解除對行動程式碼安全性的相關疑慮,並提供支援,讓元件能夠判斷哪些使用者有權執行。
類型安全和安全性
類型安全程式碼只會存取經授權存取的記憶體位置。 (這裡所討論的類型安全是專指記憶體類型安全,不應與廣義的類型安全混淆。)例如,類型安全程式碼無法從另一個物件的私用欄位讀取值。 它只會以妥善定義、可允許的方式來存取類型。
在 Just-In-Time (JIT) 編譯期間,選擇性的驗證程序會檢查中繼資料,以及要以 JIT 編譯成原生機器程式碼之方法的通用中間語言 (CIL),以驗證其類型安全。 如果程式碼具有略過驗證的權限,則會略過此程序。 如需有關驗證的詳細資訊,請參閱 Managed 執行程序。
雖然沒有強制要驗證類型安全才能執行 Managed 程式碼,但是在組件隔離和強制執行安全性的作業中,類型安全扮演相當重要的角色。 當程式碼類型安全時,Common Language Runtime 可以將組件彼此完全隔離。 此隔離有助於確保組件無法對彼此產生不利的影響,而且也會增加應用程式的可靠性。 類型安全元件即使受信任的層級不同,還是可以在相同的處理序中安全地執行。 當程式碼不是類型安全時,可能會發生不必要的副作用。 例如,執行階段無法防止 Managed 程式碼呼叫機器碼 (Unmanaged) 及執行惡意的作業。 當程式碼為類型安全時,執行階段的安全性強制機制可確保它不會存取原生程式碼,除非它有這樣的權限。 所有不是類型安全的程式碼,都必須被授與具有通過之列舉成員 SkipVerification 的 SecurityPermission,才能執行。
注意
在所有版本的 .NET Framework 與 .NET 中,程式碼存取安全性 (CAS) 均已被取代。 當使用 CAS 相關 API 時,最新版本的 .NET 不會接受 CAS 註釋,並會產生錯誤。 開發人員應尋求替代方案來完成安全性工作。
主體
主體代表使用者的身分識別與角色,並且會代表使用者採取行動。 在 .NET 中,以角色為基礎的安全性可支援三種主體:
泛型主體代表獨立於 Windows 使用者和角色而存在的使用者和角色。
Windows 主體代表 Windows 使用者及其角色 (或其 Windows 群組)。 Windows 主體可以模擬另一位使用者,這表示該主體可以代表使用者存取資源,同時呈現屬於該使用者身分識別。
自訂主體可以由應用程式以該特定應用程式所需的任何方式來定義。 其可擴充主體身分識別和角色的基本概念。
如需詳細資訊,請參閱主體和身分識別物件。
驗證
驗證是探索並確認主體身分識別的程序,它會檢查使用者的認證,並針對某授權單位來驗證那些認證。 在驗證期間取得的資訊可直接供是由您的程式碼使用。 您也可以使用 .NET 以角色為基礎的安全性來驗證目前使用者,以及判斷是否允許該主體存取您的程式碼。 請參閱 WindowsPrincipal.IsInRole 方法的多載,以取得如何針對特定角色來驗證主體的範例。 例如,您可以使用 WindowsPrincipal.IsInRole(String) 多載來判斷目前使用者是否為系統管理員群組的成員。
當今所使用的驗證機制非常多樣化,其中有許多可以搭配 .NET 以角色為基礎的安全性。 部分最常用的機制有基本、摘要式、Passport、作業系統 (例如 NTLM 或 Kerberos) 或應用程式定義的機制。
範例
下列範例需要由作用中的主體做為系統管理員。 name
參數為 null
,可讓做為系統管理員的任何使用者傳遞要求。
注意
在 Windows Vista 中,使用者帳戶控制 (UAC) 會判斷使用者的權限。 如果您是內建 Administrators 群組的成員,系統會將兩個執行階段存取語彙基元 (Token) 指派給您:標準使用者存取語彙基元及管理員存取語彙基元。 根據預設,您會屬於標準使用者角色。 若要執行需要您是系統管理員的程式碼,您必須先將權限從標準使用者提高為系統管理員。 您可以在啟動應用程式時,以滑鼠右鍵按一下應用程式圖示,並指出您想要以系統管理員身分執行,藉此提高為系統管理員權限。
using namespace System;
using namespace System::Security;
using namespace System::Security::Permissions;
using namespace System::Security::Policy;
using namespace System::Security::Principal;
int main(array<System::String ^> ^args)
{
System::String^ null;
AppDomain::CurrentDomain->SetPrincipalPolicy(PrincipalPolicy::WindowsPrincipal);
PrincipalPermission^ principalPerm = gcnew PrincipalPermission(null, "Administrators" );
principalPerm->Demand();
Console::WriteLine("Demand succeeded");
return 0;
}
using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;
class SecurityPrincipalDemo
{
public static void Main()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
PrincipalPermission principalPerm = new PrincipalPermission(null, "Administrators");
principalPerm.Demand();
Console.WriteLine("Demand succeeded.");
}
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal
Class SecurityPrincipalDemo
Public Shared Sub Main()
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
Dim principalPerm As New PrincipalPermission(Nothing, "Administrators")
principalPerm.Demand()
Console.WriteLine("Demand succeeded.")
End Sub
End Class
下列範例示範如何判斷主體的身分識別,以及可供主體使用的角色。 此範例的應用程式可能是要確認目前的使用者是您允許使用您的應用程式的角色。
public:
static void DemonstrateWindowsBuiltInRoleEnum()
{
AppDomain^ myDomain = Thread::GetDomain();
myDomain->SetPrincipalPolicy( PrincipalPolicy::WindowsPrincipal );
WindowsPrincipal^ myPrincipal = dynamic_cast<WindowsPrincipal^>(Thread::CurrentPrincipal);
Console::WriteLine( "{0} belongs to: ", myPrincipal->Identity->Name );
Array^ wbirFields = Enum::GetValues( WindowsBuiltInRole::typeid );
for each ( Object^ roleName in wbirFields )
{
try
{
Console::WriteLine( "{0}? {1}.", roleName,
myPrincipal->IsInRole( *dynamic_cast<WindowsBuiltInRole^>(roleName) ) );
}
catch ( Exception^ )
{
Console::WriteLine( "{0}: Could not obtain role for this RID.",
roleName );
}
}
}
using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;
class SecurityPrincipalDemo
{
public static void DemonstrateWindowsBuiltInRoleEnum()
{
AppDomain myDomain = Thread.GetDomain();
myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal myPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
Console.WriteLine("{0} belongs to: ", myPrincipal.Identity.Name.ToString());
Array wbirFields = Enum.GetValues(typeof(WindowsBuiltInRole));
foreach (object roleName in wbirFields)
{
try
{
// Cast the role name to a RID represented by the WindowsBuildInRole value.
Console.WriteLine("{0}? {1}.", roleName,
myPrincipal.IsInRole((WindowsBuiltInRole)roleName));
Console.WriteLine("The RID for this role is: " + ((int)roleName).ToString());
}
catch (Exception)
{
Console.WriteLine("{0}: Could not obtain role for this RID.",
roleName);
}
}
// Get the role using the string value of the role.
Console.WriteLine("{0}? {1}.", "Administrators",
myPrincipal.IsInRole("BUILTIN\\" + "Administrators"));
Console.WriteLine("{0}? {1}.", "Users",
myPrincipal.IsInRole("BUILTIN\\" + "Users"));
// Get the role using the WindowsBuiltInRole enumeration value.
Console.WriteLine("{0}? {1}.", WindowsBuiltInRole.Administrator,
myPrincipal.IsInRole(WindowsBuiltInRole.Administrator));
// Get the role using the WellKnownSidType.
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
Console.WriteLine("WellKnownSidType BuiltinAdministratorsSid {0}? {1}.", sid.Value, myPrincipal.IsInRole(sid));
}
public static void Main()
{
DemonstrateWindowsBuiltInRoleEnum();
}
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal
Class SecurityPrincipalDemo
Public Shared Sub DemonstrateWindowsBuiltInRoleEnum()
Dim myDomain As AppDomain = Thread.GetDomain()
myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
Dim myPrincipal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
Console.WriteLine("{0} belongs to: ", myPrincipal.Identity.Name.ToString())
Dim wbirFields As Array = [Enum].GetValues(GetType(WindowsBuiltInRole))
Dim roleName As Object
For Each roleName In wbirFields
Try
' Cast the role name to a RID represented by the WindowsBuildInRole value.
Console.WriteLine("{0}? {1}.", roleName, myPrincipal.IsInRole(CType(roleName, WindowsBuiltInRole)))
Console.WriteLine("The RID for this role is: " + Fix(roleName).ToString())
Catch
Console.WriteLine("{0}: Could not obtain role for this RID.", roleName)
End Try
Next roleName
' Get the role using the string value of the role.
Console.WriteLine("{0}? {1}.", "Administrators", myPrincipal.IsInRole("BUILTIN\" + "Administrators"))
Console.WriteLine("{0}? {1}.", "Users", myPrincipal.IsInRole("BUILTIN\" + "Users"))
' Get the role using the WindowsBuiltInRole enumeration value.
Console.WriteLine("{0}? {1}.", WindowsBuiltInRole.Administrator, myPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
' Get the role using the WellKnownSidType.
Dim sid As New SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, Nothing)
Console.WriteLine("WellKnownSidType BuiltinAdministratorsSid {0}? {1}.", sid.Value, myPrincipal.IsInRole(sid))
End Sub
Public Shared Sub Main()
DemonstrateWindowsBuiltInRoleEnum()
End Sub
End Class
授權
授權是決定是否允許主體執行所要求動作的程序。 授權會在驗證之後進行,它會使用主體的身分識別和角色相關資訊來判斷主體可以存取哪些資源。 您可以使用 .NET 以角色為基礎的安全性來實作授權。