Concetti chiave sulla sicurezza
Nota
Questo articolo si applica a Windows.
Per informazioni su ASP.NET Core, vedere Panoramica di ASP.NET Core Security.
.NET offre sicurezza basata sui ruoli per risolvere i problemi di sicurezza relativi al codice mobile e fornire supporto che consente ai componenti di determinare quali utenti sono autorizzati a eseguire.
Sicurezza dei tipi e protezione
Il codice type-safe accede solo alle locazioni di memoria a cui è autorizzato ad accedere. Per questa discussione, la sicurezza dei tipi si riferisce specificamente alla sicurezza dei tipi di memoria e non deve essere confusa con la sicurezza dei tipi in un contesto più ampio. Ad esempio, il codice indipendente dai tipi non può leggere i valori dai campi privati di un altro oggetto. Accede ai tipi solo in modi ben definiti e consentiti.
Durante la compilazione JIT (Just-In-Time), un processo di verifica facoltativo esamina i metadati e il linguaggio intermedio comune (CIL) di un metodo che deve essere compilato JIT in codice macchina nativo per verificare che siano sicuri in termini di tipi. Questo processo viene ignorato se il codice dispone dell'autorizzazione per ignorare la verifica. Per altre informazioni sulla verifica, vedere processo di esecuzione gestita.
Anche se la verifica della sicurezza del tipo non è obbligatoria per l'esecuzione del codice gestito, la sicurezza del tipo svolge un ruolo fondamentale nell'isolamento dell'assembly e nell'applicazione della sicurezza. Quando il codice è a sicurezza di tipo, il common language runtime può isolare completamente gli assembly tra loro. Questo isolamento consente di garantire che gli assembly non possano influire negativamente l'uno sull'altro e aumentano l'affidabilità dell'applicazione. I componenti con sicurezza di tipo possono essere eseguiti in modo sicuro nello stesso processo anche se sono attendibili a livelli diversi. Quando il codice non è di tipo sicuro, possono verificarsi effetti collaterali indesiderati. Ad esempio, il runtime non può impedire al codice gestito di chiamare codice nativo (non gestito) ed eseguire operazioni dannose. Quando il codice è tipo sicuro, il meccanismo di imposizione della sicurezza del runtime garantisce che non accederà al codice nativo, a meno che non disponga delle autorizzazioni necessarie. A tutto il codice che non è sicuro per tipi deve essere concesso SecurityPermission insieme al membro dell'enumerazione passato SkipVerification per poter essere eseguito.
Nota
La sicurezza dall'accesso al codice è stata deprecata in tutte le versioni di .NET Framework e .NET. Le versioni recenti di .NET non rispettano le annotazioni CAS e generano errori se vengono usate API correlate a CAS. Gli sviluppatori devono cercare mezzi alternativi per eseguire attività di sicurezza.
Preside
Un principale rappresenta l'identità e il ruolo di un utente e agisce per conto dell'utente. La sicurezza in .NET basata sui ruoli supporta tre tipi di principi:
Le entità generiche rappresentano utenti e ruoli che esistono indipendentemente da utenti e ruoli di Windows.
I principali di Windows rappresentano gli utenti di Windows e i loro ruoli (o i loro gruppi di Windows). Un'entità di Windows può rappresentare un altro utente, il che significa che l'entità può accedere a una risorsa per conto di un utente presentando l'identità appartenente a tale utente.
I principi personalizzati possono essere definiti da un'applicazione in qualsiasi modo necessario per quell'applicazione. Possono estendere la nozione di base dell'identità e dei ruoli del principale.
Per altre informazioni, vedere Oggetti Principali e di Identità.
Autenticazione
L'autenticazione è il processo di individuazione e verifica dell'identità di un'entità esaminando le credenziali dell'utente e convalidando tali credenziali in base a un'autorità. Le informazioni ottenute durante l'autenticazione sono utilizzabili direttamente dal codice. È anche possibile usare la sicurezza basata sui ruoli .NET per autenticare l'utente corrente e determinare se consentire a tale entità di accedere al codice. Consultare i sovraccarichi del metodo WindowsPrincipal.IsInRole per esempi di come autenticare il principale per ruoli specifici. Ad esempio, è possibile usare l'overload WindowsPrincipal.IsInRole(String) per determinare se l'utente corrente è membro del gruppo Administrators.
Attualmente vengono usati diversi meccanismi di autenticazione, molti dei quali possono essere usati con la sicurezza basata sui ruoli .NET. Alcuni dei meccanismi più usati sono di base, digest, Passport, sistema operativo (ad esempio NTLM o Kerberos) o meccanismi definiti dall'applicazione.
Esempio
L'esempio seguente richiede che l'entità attiva sia un amministratore. Il parametro name
è null
, che consente a qualsiasi utente che è un amministratore di passare la richiesta.
Nota
In Windows Vista il controllo dell'account utente determina i privilegi di un utente. Se si è membri del gruppo Administrators predefinito, vengono assegnati due token di accesso in fase di esecuzione: un token di accesso utente standard e un token di accesso amministratore. Per impostazione predefinita, si è nel ruolo utente standard. Per eseguire il codice che richiede di essere un amministratore, è prima necessario elevare i privilegi dall'utente standard all'amministratore. A tale scopo, è possibile avviare un'applicazione facendo clic con il pulsante destro del mouse sull'icona dell'applicazione e indicando che si vuole eseguire come amministratore.
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
Nell'esempio seguente viene illustrato come determinare l'identità dell'entità e i ruoli disponibili per l'entità. Un'applicazione di questo esempio potrebbe essere quella di confermare che l'utente corrente si trova in un ruolo consentito per l'uso dell'applicazione.
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($"{roleName}: Could not obtain role for this RID.");
}
}
// 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
Autorizzazione
L'autorizzazione è il processo per determinare se un'entità è autorizzata a eseguire un'azione richiesta. L'autorizzazione viene eseguita dopo l'autenticazione e usa informazioni sull'identità e sui ruoli dell'entità per determinare le risorse a cui l'entità può accedere. È possibile usare la sicurezza basata sui ruoli .NET per implementare l'autorizzazione.