Dato un nome utente e una password, come faccio a impersonare quell'utente ed eseguire del codice come tale utente.Come impersonare un utente nel codice gestito?
E per gestita voglio dire senza pinvokes o dllimports
Dato un nome utente e una password, come faccio a impersonare quell'utente ed eseguire del codice come tale utente.Come impersonare un utente nel codice gestito?
E per gestita voglio dire senza pinvokes o dllimports
Questa è la classe wrapper abbiamo creato che ha funzionato su diverse piattaforme Windows:
public class Impersonator
{
// constants from winbase.h
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_LOGON_NETWORK = 3;
public const int LOGON32_LOGON_BATCH = 4;
public const int LOGON32_LOGON_SERVICE = 5;
public const int LOGON32_LOGON_UNLOCK = 7;
public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_PROVIDER_WINNT35 = 1;
public const int LOGON32_PROVIDER_WINNT40 = 2;
public const int LOGON32_PROVIDER_WINNT50 = 3;
[DllImport("advapi32.dll", SetLastError=true)]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public static WindowsImpersonationContext LogOn(string userName, string password)
{
return LogOn(userName, password, "");
}
public static WindowsImpersonationContext LogOn(string userName, string password, string domain)
{
WindowsIdentity tempWindowsIdentity;
WindowsImpersonationContext impersonationContext;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return impersonationContext;
}
}
}
else
{
var win32 = new Win32Exception(Marshal.GetLastWin32Error());
//throw new Exception(string.Format("{0}, Domain:{1}, User:{2}, Password:{3}",
// win32.Message, domain, userName, password));
throw new Exception(win32.Message);
}
}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
return null; // Failed to impersonate
}
public static bool LogOff(WindowsImpersonationContext context)
{
bool result = false;
try
{
if (context != null)
{
context.Undo();
result = true;
}
}
catch
{
result = false;
}
return result;
}
}
C'è una domanda simile con una grande risposta here.
Dai un'occhiata alla WindowsImpersonationContext
per qualche informazione in più (anche lì è un altro esempio di codice grande lì)
era curioso se poteva essere fatto senza alcun dllimports – Simon
Se si tratta di un sito Web ASP.NET, allora sì può essere fatto impostando l'elemento '
@Simon: la rappresentazione è utile anche durante le installazioni o l'esecuzione di un'applicazione "come" qualcun altro, ad esempio un amministratore .. – AMissico
Vedi ImpersonationHelper
di Is it possible to safely get a SecureString value from VB .NET?. Il codice è pronto per la produzione e robusto.
Supporta IDisposable
, contiene un metodo RunAs
(che è di valore inestimabile), le password vengono gestite come SecureString
e altri piccoli extra utili. Ho anche fornito il codice di test per la classe ImpersonationHelper
estremamente utile per la risoluzione dei problemi e sono i metodi di estenzione SecureString
che risultano utili.
ho bollito giù a due semplici metodi:
public bool ImpersonateValidUser(String userName, String domain, String password)
public void UndoImpersonation()
È possibile directlyh copia/incolla il codice categoria qui sotto e utilizzarlo nel progetto:
class ImpersonationContext
{
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_PROVIDER_WINNT50 = 3;
WindowsImpersonationContext impersonationContext;
public bool ImpersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_WINNT50, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
public void UndoImpersonation()
{
impersonationContext.Undo();
}
}
Certo, si riduce a due metodi. non ha errori nella gestione e se si verifica un errore, non rilascia le maniglie create. – AMissico
Tutti gli esempi che ho visto non riescono a t tenere conto del fatto che il tipo di accesso non è una soluzione adatta a tutte le dimensioni.
Ad esempio, questo funzionerà solo se l'utente che si sta impersonando dispone dell'autorizzazione per l'accesso al sistema di destinazione. Non sempre accade quando si accede a una casella remota di SQL Server. LOGON32_LOGON_INTERACTIVE
NetworkClearText è l'unico che funziona in modo coerente per l'utilizzo con le connessioni di SQL Server. - Nessun testo chiaro non significa che sta trasmettendo le credenziali in modo non sicuro.
Quando su un gruppo di lavoro e è necessario impersonare un utente di dominio NewCredentials è quello che funziona. (non testato con le connessioni di SQL Server)
ha funzionato alla grande John. Grazie – GR7
Prego, silverCORE –
Dove hai trovato i valori LOGON32_PROVIDER_x? –