"Rappresentazione" nello spazio .NET generalmente significa eseguire codice con un account utente specifico. È un concetto un po 'separato rispetto all'accesso a quell'account utente tramite un nome utente e una password, sebbene queste due idee si accoppino frequentemente. Li descriverò entrambi e poi spiegherò come usare la mia libreria SimpleImpersonation , che li usa internamente.
imitazione
Le API per la rappresentazione sono fornite in .NET tramite lo System.Security.Principal
spazio dei nomi:
In genere dovrebbe essere utilizzato WindowsIdentity.RunImpersonated
un codice più recente (.NET 4.6+, .NET Core, ecc.) , Che accetta un handle per il token dell'account utente e quindi un Action
o Func<T>
per l'esecuzione del codice.
WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
});
o
var result = WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
return result;
});
Il codice precedente utilizzava il WindowsIdentity.Impersonate
metodo per recuperare un WindowsImpersonationContext
oggetto. Questo oggetto implementa IDisposable
, quindi generalmente dovrebbe essere chiamato da un using
blocco.
using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(tokenHandle))
{
// do whatever you want as this user.
}
Sebbene questa API sia ancora presente in .NET Framework, in genere dovrebbe essere evitata e non è disponibile in .NET Core o .NET Standard.
Accesso all'account utente
L'API per l'utilizzo di un nome utente e una password per ottenere l'accesso a un account utente in Windows è LogonUser
- che è un'API nativa Win32. Al momento non esiste un'API .NET integrata per chiamarla, quindi è necessario ricorrere a P / Invoke.
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
Questa è la definizione di base della chiamata, tuttavia c'è molto di più da considerare per usarlo effettivamente in produzione:
- Ottenere una maniglia con il modello di accesso "sicuro".
- Chiudere gli handle nativi in modo appropriato
- Livelli di affidabilità della protezione dall'accesso di codice (CAS) (solo in .NET Framework)
- Passa
SecureString
quando puoi raccoglierne uno in modo sicuro tramite i tasti utente.
La quantità di codice da scrivere per illustrare tutto ciò va oltre ciò che dovrebbe essere in una risposta StackOverflow, IMHO.
Un approccio combinato e più semplice
Invece di scrivere tutto questo da solo, prendi in considerazione l'uso della mia libreria SimpleImpersonation , che combina la rappresentazione e l'accesso dell'utente in un'unica API. Funziona bene con basi di codice sia moderne che precedenti, con la stessa semplice API:
var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
});
o
var credentials = new UserCredentials(domain, username, password);
var result = Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
return something;
});
Si noti che è molto simile WindowsIdentity.RunImpersonated
all'API, ma non richiede di conoscere nulla sugli handle di token.
Questa è l'API a partire dalla versione 3.0.0. Vedere il file Leggimi del progetto per maggiori dettagli. Si noti inoltre che una versione precedente della libreria utilizzava un'API con il IDisposable
modello, simile a WindowsIdentity.Impersonate
. La versione più recente è molto più sicura ed entrambe sono ancora utilizzate internamente.