Se si utilizza il codice quanto segue di impersonare un altro utente,L'accesso tramite impersonation .NET è thread-safe?
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool
LogonUser(string lpszUsername, string lpszDomain,
string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
var handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
LogonUser(username, domain,
password, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, ref handle))
su due diversi thread concorrenti, faranno interferiscono uno con l'altro? Ad esempio, l'utente attualmente connesso è associato al thread o al processo host?
Sto utilizzando l'handle di accesso per creare un oggetto WindowsImpersonationContext, come campo di stato privato in un'istanza di un tipo denominato "Impersonator" (codice di seguito). Quindi, poiché questo oggetto WindowsImpersonationContext è un campo privato locale in un'istanza di questo tipo e viene creata una nuova istanza di questo tipo ogni volta che voglio impersonare un gruppo di credenziali, posso presumere che questo WindowsImpersonationContext sia quello a cui si sta abituando eseguire tutte le convalide ACL durante l'esecuzione di codice all'interno di un blocco come
using (Impersonator.Impersonate(userId, domain, password))
{
// Code I want to execute using supplied credentials
}
cosa mi ha preoccupato è la dichiarazione sulla pagina MSDN WindowsImpersonationContext che dice:
statici pubblici (Shared in Visual Basic) membri di questo tipo sono thread-safe. Non è garantito che tutti i membri di istanza siano thread-safe.
Impersonator
classe:
public class Impersonator: IDisposable
{
#region Declarations
private readonly string username;
private readonly string password;
private readonly string domain;
// This will hold the security context
// for reverting back to the client after
// impersonation operations are complete
private WindowsImpersonationContext impersonationContext;
#endregion Declarations
#region Constructors
public Impersonator(string UserName,
string Domain, string Password)
{
username = UserName;
domain = Domain;
password = Password;
}
#endregion Constructors
#region Public Methods
public static Impersonator Impersonate(
string userName, string domain, string password)
{
var imp = new Impersonator(userName, domain, password);
imp.Impersonate();
return imp;
}
public void Impersonate()
{
impersonationContext = Logon().Impersonate();
}
public void Undo() {
impersonationContext.Undo();
}
#endregion Public Methods
#region Private Methods
private WindowsIdentity Logon()
{
var handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
// Attempt to authenticate domain user account
try
{
if (!LogonUser(username, domain,
password, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, ref handle))
throw new LogonException(
"User logon failed. Error Number: " +
Marshal.GetLastWin32Error());
// ----------------------------------
var dupHandle = IntPtr.Zero;
if (!DuplicateToken(handle,
SecurityImpersonation,
ref dupHandle))
throw new LogonException(
"Logon failed attemting to duplicate handle");
// Logon Succeeded ! return new WindowsIdentity instance
return (new WindowsIdentity(handle));
}
// Close the open handle to the authenticated account
finally { CloseHandle(handle); }
}
#region external Win32 API functions
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool
LogonUser(string lpszUsername, string lpszDomain,
string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
// --------------------------------------------
[DllImport("advapi32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool DuplicateToken(
IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr DuplicateTokenHandle);
// --------------------------------------------
#endregion external Win32 API functions
#endregion Private Methods
#region IDisposable
private bool disposed;
public void Dispose() { Dispose(true); }
public void Dispose(bool isDisposing)
{
if (disposed)
return;
if (isDisposing)
Undo();
// -----------------
disposed = true;
GC.SuppressFinalize(this);
}
~Impersonator() {
Dispose(false);
}
#endregion IDisposable
}
destro, io uso l'impugnatura per creare un oggetto WindowsImpersonationContext, che è thread-safe, (è un esempio di un tipo definito creato uno ad utilizzo). Con "associato", intendevo dire dove è memorizzato quel logon di accesso? A quanto ho capito, è questo oggetto WindowsImpersonationContext che "contiene" il riferimento al contesto di sicurezza, e se questo non è condiviso su thread, dovrei essere ok ... giusto? –
Quello che mi ha preoccupato è la dichiarazione sulla pagina http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx MSDN che dice: "statici pubblici (Shared in Visual Basic) i membri di questo tipo sono thread-safe. Non è garantito che tutti i membri di istanza siano thread-safe. " –
@Charles Bretana: i membri dell'istanza dell'istanza WindowsImpersonationContext non sono thread-safe. Non è possibile effettuare chiamate alla stessa istanza da più thread con sicurezza garantita. Questo oggetto è come la maggior parte degli altri in .NET, i membri di istanza non sono thread-safe, i membri statici lo sono. Per quanto riguarda la posizione in cui è archiviato l'handle di accesso, l'handle si trova in IntPtr, che indica le informazioni per il token di accesso. – casperOne