Główne pojęcia dotyczące zabezpieczeń
Uwaga
Ten artykuł dotyczy systemu Windows.
Aby uzyskać informacje o ASP.NET Core, zobacz Omówienie ASP.NET Core Security.
Platforma .NET oferuje zabezpieczenia oparte na rolach, aby pomóc w rozwiązywaniu problemów z zabezpieczeniami dotyczących kodu mobilnego i zapewnianiu pomocy technicznej, która umożliwia składnikom określenie, którzy użytkownicy mają uprawnienia do wykonania.
Bezpieczeństwo i zabezpieczenia typów
Kod bezpieczny pod kątem typu uzyskuje dostęp tylko do lokalizacji pamięci, do których ma dostęp. (Na potrzeby tej dyskusji bezpieczeństwo typu odnosi się konkretnie do bezpieczeństwa typu pamięci i nie należy mylić z bezpieczeństwem typu w szerszym zakresie). Na przykład kod bezpieczny typu nie może odczytywać wartości z pól prywatnych innego obiektu. Uzyskuje dostęp do typów tylko w dobrze zdefiniowanych, dozwolonych sposobach.
Podczas kompilacji just in time (JIT) opcjonalny proces weryfikacji sprawdza metadane i wspólny język pośredni (CIL) metody, która ma być kompilowana w natywnym kodzie maszynowym, aby sprawdzić, czy są one bezpieczne. Ten proces jest pomijany, jeśli kod ma uprawnienia do obejścia weryfikacji. Aby uzyskać więcej informacji na temat weryfikacji, zobacz Proces wykonywania zarządzanego.
Chociaż weryfikacja bezpieczeństwa typu nie jest obowiązkowa do uruchamiania kodu zarządzanego, bezpieczeństwo typu odgrywa kluczową rolę w izolacji zestawu i wymuszaniu zabezpieczeń. Gdy kod jest bezpieczny, środowisko uruchomieniowe języka wspólnego może całkowicie odizolować zestawy od siebie. Ta izolacja pomaga zapewnić, że zestawy nie mogą niekorzystnie wpływać na siebie i zwiększa niezawodność aplikacji. Składniki bezpieczne dla typów mogą być bezpiecznie wykonywane w tym samym procesie, nawet jeśli są zaufane na różnych poziomach. Gdy kod nie jest bezpieczny, mogą wystąpić niepożądane skutki uboczne. Na przykład środowisko uruchomieniowe nie może uniemożliwić wywoływania kodu zarządzanego do natywnego (niezarządzanego) kodu i wykonywania złośliwych operacji. Gdy kod jest bezpieczny, mechanizm wymuszania zabezpieczeń środowiska uruchomieniowego zapewnia, że nie uzyskuje dostępu do kodu natywnego, chyba że ma uprawnienia do tego. Cały kod, który nie jest typem bezpieczny, musi zostać udzielony SecurityPermission z przekazanym elementem SkipVerification wyliczenia do uruchomienia.
Uwaga
Zabezpieczenia dostępu kodu (CAS) zostały wycofane we wszystkich wersjach programu .NET Framework i .NET. Najnowsze wersje platformy .NET nie honorują adnotacji CAS i generują błędy, jeśli są używane interfejsy API związane z usługą CAS. Deweloperzy powinni szukać alternatywnych sposobów wykonywania zadań zabezpieczeń.
Główne
Podmiot zabezpieczeń reprezentuje tożsamość i rolę użytkownika i działa w imieniu użytkownika. Zabezpieczenia oparte na rolach na platformie .NET obsługują trzy rodzaje podmiotów zabezpieczeń:
Ogólne podmioty zabezpieczeń reprezentują użytkowników i role, które istnieją niezależnie od użytkowników i ról systemu Windows.
Podmioty zabezpieczeń systemu Windows reprezentują użytkowników systemu Windows i ich role (lub grupy systemu Windows). Podmiot zabezpieczeń systemu Windows może personifikować innego użytkownika, co oznacza, że podmiot zabezpieczeń może uzyskać dostęp do zasobu w imieniu użytkownika podczas prezentowania tożsamości należącej do tego użytkownika.
Jednostki niestandardowe mogą być definiowane przez aplikację w dowolny sposób, który jest wymagany dla tej konkretnej aplikacji. Mogą rozszerzyć podstawowe pojęcie tożsamości i ról podmiotu zabezpieczeń.
Aby uzyskać więcej informacji, zobacz Obiekty podmiotu zabezpieczeń i tożsamości.
Uwierzytelnianie
Uwierzytelnianie to proces odnajdywania i weryfikowania tożsamości podmiotu zabezpieczeń przez sprawdzenie poświadczeń użytkownika i zweryfikowanie tych poświadczeń względem określonego urzędu. Informacje uzyskane podczas uwierzytelniania są bezpośrednio używane przez kod. Możesz również użyć zabezpieczeń opartych na rolach platformy .NET, aby uwierzytelnić bieżącego użytkownika i określić, czy zezwolić tej jednostce na dostęp do kodu. Zobacz przeciążenia metody , WindowsPrincipal.IsInRole aby zapoznać się z przykładami uwierzytelniania podmiotu zabezpieczeń dla określonych ról. Na przykład można użyć WindowsPrincipal.IsInRole(String) przeciążenia, aby określić, czy bieżący użytkownik jest członkiem grupy Administracja istrators.
Obecnie są używane różne mechanizmy uwierzytelniania, z których wiele może być używanych z zabezpieczeniami opartymi na rolach platformy .NET. Niektóre z najczęściej używanych mechanizmów to podstawowe, szyfrowane, passport, system operacyjny (np. NTLM lub Kerberos) lub mechanizmy zdefiniowane przez aplikację.
Przykład
Poniższy przykład wymaga, aby aktywny podmiot zabezpieczeń był administratorem. Parametr name
to null
, który umożliwia każdemu użytkownikowi, który jest administratorem, przekaże żądanie.
Uwaga
W systemie Windows Vista kontrola konta użytkownika (UAC) określa uprawnienia użytkownika. Jeśli jesteś członkiem wbudowanej grupy Administratorzy, masz przypisane dwa tokeny dostępu w czasie wykonywania: token dostępu użytkownika standardowego i token dostępu administratora. Domyślnie jesteś w roli użytkownika standardowego. Aby wykonać kod, który wymaga, aby być administratorem, musisz najpierw podnieść swoje uprawnienia od użytkownika standardowego do administratora. Możesz to zrobić po uruchomieniu aplikacji, klikając prawym przyciskiem myszy ikonę aplikacji i wskazując, że chcesz uruchomić jako administrator.
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
W poniższym przykładzie pokazano, jak określić tożsamość podmiotu zabezpieczeń i ról dostępnych dla podmiotu zabezpieczeń. Zastosowaniem tego przykładu może być potwierdzenie, że bieżący użytkownik znajduje się w roli, którą zezwalasz na korzystanie z aplikacji.
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
Autoryzacja
Autoryzacja to proces określania, czy podmiot zabezpieczeń może wykonać żądaną akcję. Autoryzacja następuje po uwierzytelnieniu i używa informacji o tożsamości i rolach podmiotu zabezpieczeń w celu określenia, do jakich zasobów może uzyskiwać dostęp podmiot zabezpieczeń. Aby zaimplementować autoryzację, można użyć zabezpieczeń opartych na rolach platformy .NET.