Concetti chiave sulla sicurezza
Nota
Questo articolo si applica a Windows.
Per informazioni su ASP.NET Core, vedere Panoramica di Sicurezza ASP.NET Core.
.NET offre la sicurezza basata sui ruoli per risolvere i problemi di sicurezza relativi al codice mobile e per fornire un supporto che consenta di abilitare i componenti per determinare le operazioni per cui gli utenti dispongono di autorizzazioni.
Indipendenza dai tipi e sicurezza
Il codice indipendente dai tipi accede solo alle posizioni di memoria per le quali dispone di autorizzazioni. In questo contesto, per indipendenza dai tipi si intende l'indipendenza dai tipi di memoria, che non deve essere confusa con il concetto più generico di indipendenza dai tipi. Ad esempio, un codice indipendente dai tipi non può leggere i valori dei campi privati di un altro oggetto. Accede ai tipi solo in modalità ben definite e consentite.
Durante la compilazione JIT (Just-In-Time), un processo di verifica facoltativo esamina i metadati e il linguaggio intermedio comune (CIL) di un metodo per la compilazione JIT nel codice macchina nativo per verificare che siano indipendenti dai 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.
Sebbene la verifica dell'indipendenza dai tipi non sia obbligatoria per l'esecuzione di codice gestito, l'indipendenza dai tipi ha un ruolo fondamentale nell'imposizione della sicurezza e nell'isolamento dell'assembly. Quando il codice è indipendente dai tipi, Common Language Runtime può isolare completamente i singoli assembly. Questo isolamento contribuisce a garantire che gli assembly non interferiscano tra loro, aumentando l'affidabilità dell'applicazione. I componenti indipendenti dai tipi possono essere eseguiti in modo sicuro nello stesso processo anche se sono attendibili a livelli diversi. Quando il codice non è indipendente dai tipi possono verificarsi effetti collaterali indesiderati. Il runtime, ad esempio, non è in grado di impedire al codice gestito di effettuare chiamate a codice nativo (non gestito) e di eseguire operazioni dannose. Quando il codice è indipendente dai tipi, il meccanismo di imposizione della sicurezza del runtime ne impedisce l'accesso al codice nativo a meno che non disponga delle autorizzazioni. Per essere eseguito, tutto il codice non indipendente dai tipi deve aver ottenuto SecurityPermission con il membro di enumerazione passato SkipVerification.
Nota
La sicurezza dall'accesso al codice (CAS) è 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 alla CAS. Gli sviluppatori devono cercare mezzi alternativi per eseguire attività di sicurezza.
Entità di sicurezza
Un'entità rappresenta l'identità e il ruolo di un utente e agisce per conto dell'utente. La sicurezza basata sui ruoli in .NET supporta tre tipi di entità:
Le entità generiche rappresentano utenti e ruoli che esistono indipendentemente dai ruoli e dagli utenti di Windows.
Le entità di Windows rappresentano gli utenti di Windows e i relativi ruoli (o i 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 dell'utente presentando l'identità appartenente a tale utente.
Le entità personalizzate possono essere definite da un'applicazione secondo le modalità richieste dalla specifica applicazione. Possono estendere la nozione di base di identità e di ruoli dell'entità.
Per altre informazioni, vedere Oggetti Principal e Identity.
Autenticazione
L'autenticazione è il processo di individuazione e verifica dell'identità di un'entità eseguito esaminando e convalidando le credenziali dell'utente rispetto a un'autorità specificata. Le informazioni ottenute durante l'autenticazione possono essere usate direttamente dal codice. È anche possibile usare la sicurezza basata sui ruoli di .NET per autenticare l'utente corrente e per determinare se consentire a tale entità di accedere al codice. Vedere gli overload del metodo WindowsPrincipal.IsInRole per esempi su come autenticare l'entità per ruoli specifici. Ad esempio, è possibile usare l'overload WindowsPrincipal.IsInRole(String) per determinare se l'utente corrente è un membro del gruppo Administrators.
Un'ampia gamma di meccanismi di autenticazione usati oggi, molti dei quali possono essere usati con la sicurezza basata sui ruoli di .NET. Alcuni dei meccanismi più diffusi sono il meccanismo di base, il digest, il Passport, il sistema operativo (ad esempio NTLM o Kerberos) o i 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 con ruolo di amministratore di passare la richiesta.
Nota
In Windows Vista, la funzionalità Controllo dell'account utente determina i privilegi di un utente. Ai membri del gruppo Administrators predefinito vengono assegnati due token di accesso in fase di esecuzione, ovvero un token di accesso utente standard e un token di accesso amministratore. Per impostazione predefinita, viene assegnato il ruolo dell'utente standard. Per eseguire il codice che richiede un ruolo da amministratore è necessario elevare i privilegi da utente standard ad amministratore. È possibile farlo quando si avvia un'applicazione facendo clic con il pulsante destro del mouse sull'icona dell'applicazione e indicando l'opzione di esecuzione 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
L'esempio seguente mostra come determinare l'identità dell'entità e i ruoli disponibili per l'entità. Un'applicazione di questo esempio potrebbe essere la conferma che l'utente corrente ha un ruolo autorizzato all'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("{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
Autorizzazione
L'autorizzazione è il processo che consente di determinare se un'entità è autorizzata a eseguire un'azione richiesta. L'autorizzazione si verifica dopo l'autenticazione e usa le informazioni di identità e i ruoli dell'entità per determinare a quali risorse può accedere. È possibile usare la sicurezza basata sui ruoli di .NET per implementare l'autorizzazione.