Klíčové koncepty zabezpečení
Poznámka:
Tento článek se týká Windows.
Informace o ASP.NET Core najdete v tématu Přehled zabezpečení ASP.NET Core.
.NET nabízí zabezpečení založené na rolích, které pomáhá řešit bezpečnostní otázky týkající se mobilního kódu a poskytovat podporu, která umožňuje komponentám určit, kteří uživatelé mají oprávnění dělat.
Zabezpečení a zabezpečení typů
Typově bezpečný kód přistupuje pouze k umístěním paměti, ke které má oprávnění přistupovat. (Pro tuto diskuzi se bezpečnost typů týká konkrétně bezpečnosti typů a neměla by být zaměňována s bezpečností typů v širším ohledu.) Například typově bezpečný kód nemůže číst hodnoty z privátních polí jiného objektu. Přistupuje k typům pouze v dobře definovaných, povolených způsobech.
Během kompilace JIT (just-in-time) proces volitelného ověření prozkoumá metadata a běžný zprostředkující jazyk (CIL) metody, které se mají zkompilovat do nativního strojového kódu, a ověří, že jsou typově bezpečné. Tento proces se přeskočí, pokud má kód oprávnění k obejití ověření. Další informace o ověření naleznete v tématu Spravovaný proces spuštění.
I když není ověření bezpečnosti typů povinné ke spouštění spravovaného kódu, hraje bezpečnost typů zásadní roli při izolaci sestavení a vynucování zabezpečení. Pokud je kód bezpečný, může modul CLR (Common Language Runtime) zcela izolovat sestavení od sebe. Tato izolace pomáhá zajistit, aby sestavení nemohla nepříznivě ovlivnit navzájem a zvyšuje spolehlivost aplikace. Komponenty bezpečného typu se můžou bezpečně spouštět ve stejném procesu, i když jsou důvěryhodné na různých úrovních. Pokud kód není typu bezpečný, může dojít k nežádoucím vedlejším účinkům. Modul runtime například nemůže zabránit volání spravovaného kódu do nativního (nespravovaného) kódu a provádění škodlivých operací. Pokud je kód bezpečný, mechanismus vynucení zabezpečení modulu runtime zajišťuje, že nemá přístup k nativnímu kódu, pokud k tomu nemá oprávnění. Ke spuštění veškerého kódu, který není typu bezpečný, musí být udělen SecurityPermission předaný člen SkipVerification výčtu.
Poznámka:
Zabezpečení přístupu kódu (CAS) je zastaralé ve všech verzích rozhraní .NET Framework a .NET. Nedávné verze rozhraní .NET nedotknou poznámek CAS a generují chyby, pokud se používají rozhraní API související s casem. Vývojáři by měli hledat alternativní způsoby provádění úloh zabezpečení.
Objekt zabezpečení
Objekt zabezpečení představuje identitu a roli uživatele a jedná jménem uživatele. Zabezpečení na základě rolí v .NET podporuje tři typy objektů zabezpečení:
Obecné objekty zabezpečení představují uživatele a role, které existují nezávisle na uživatelích a rolích Systému Windows.
Objekty zabezpečení systému Windows představují uživatele Systému Windows a jejich role (nebo jejich skupiny Windows). Instanční objekt Windows může zosobnit jiného uživatele, což znamená, že objekt zabezpečení má přístup k prostředku jménem uživatele při prezentování identity, která patří danému uživateli.
Vlastní objekty zabezpečení je možné definovat aplikací jakýmkoli způsobem, který je pro danou aplikaci potřeba. Můžou rozšířit základní představu o identitě a rolích objektu zabezpečení.
Další informace naleznete v tématu Objekty zabezpečení a identity.
Ověřování
Ověřování je proces zjišťování a ověření identity objektu zabezpečení prozkoumáním přihlašovacích údajů uživatele a ověřením těchto přihlašovacích údajů vůči určité autoritě. Informace získané během ověřování jsou přímo použitelné vaším kódem. Zabezpečení na základě role .NET můžete použít také k ověření aktuálního uživatele a k určení, jestli má tento objekt zabezpečení umožnit přístup k vašemu kódu. Příklady ověření objektu zabezpečení pro konkrétní role najdete v přetížení WindowsPrincipal.IsInRole metody. Přetížení můžete například použít WindowsPrincipal.IsInRole(String) k určení, zda je aktuální uživatel členem skupiny Správa istrators.
Dnes se používá celá řada ověřovacích mechanismů, z nichž mnohé se dají použít se zabezpečením na základě rolí .NET. Mezi nejčastěji používané mechanismy patří základní, digest, Passport, operační systém (například NTLM nebo Kerberos) nebo mechanismy definované aplikací.
Příklad
Následující příklad vyžaduje, aby aktivní objekt zabezpečení byl správcem. Parametr name
je null
, který umožňuje všem uživatelům, kteří jsou správcem, předat poptávku.
Poznámka:
V systému Windows Vista určuje řízení uživatelských účtů (UAC) oprávnění uživatele. Pokud jste členem předdefinované skupiny Administrators, máte přiřazeny dva přístupové tokeny run-time: token přístupu uživatele se standardním oprávněním a token přístupu správce. Ve výchozím nastavení máte roli standardního uživatele. Pokud chcete spustit kód, který vyžaduje, abyste byl správcem, musíte nejprve zvýšit oprávnění od standardního uživatele na správce. Můžete to udělat, když spustíte aplikaci tak, že kliknete pravým tlačítkem myši na ikonu aplikace a označíte, že chcete spustit jako správce.
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
Následující příklad ukazuje, jak určit identitu objektu zabezpečení a role dostupné pro objekt zabezpečení. Aplikace tohoto příkladu může být potvrzení, že aktuální uživatel je v roli, kterou povolíte používat.
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
Autorizace
Autorizace je proces určení, jestli má objekt zabezpečení povoleno provádět požadovanou akci. Autorizace probíhá po ověření a pomocí informací o identitě a rolích objektu zabezpečení určí, k jakým prostředkům má objekt zabezpečení přístup. K implementaci autorizace můžete použít zabezpečení založené na rolích .NET.