windowsimpersonationcontext true simple password net logonuser impersonator impersonate example domain c# io impersonation

c# - true - ¿Abrir un archivo compartido en otro usuario y dominio?



simple impersonation c# example (3)

Desde la memoria necesitarás usar una llamada a la API de Windows e iniciar sesión como usuario en el otro dominio. Vea este enlace para un ejemplo.

Otra idea podría ser utilizar el argumento de la línea de comandos RunAs para leer el archivo y guardarlo en un archivo en su dominio / servidor local.

Tengo una aplicación de consola C # que necesita leer un archivo compartido en una máquina en otro dominio. Cuando la aplicación intenta acceder al archivo, se produce una excepción ya que el usuario local no tiene permiso para acceder al recurso compartido.

Actualmente supero este problema de forma manual al abrir la carpeta compartida de la ejecución y coloco el nombre de usuario y la contraseña en el cuadro de diálogo de autenticación de Windows y luego ejecuto la aplicación.

¿Cómo puedo hacerlo programáticamente?


Utilicé el punto "a" como sugirió "Anton", desarrollé dos versiones para una clase, la primera con API Win32 y la segunda con la clase WindowsIdentity

Versión 1:

class UserImpersonation:IDisposable { [DllImport("advapi32.dll")] public static extern int LogonUser(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); const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; WindowsImpersonationContext wic; string _userName; string _domain; string _passWord; public UserImpersonation(string userName, string domain, string passWord) { _userName = userName; _domain = domain; _passWord = passWord; } public bool ImpersonateValidUser() { WindowsIdentity wi; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if (RevertToSelf()) { if (LogonUser(_userName, _domain, _passWord, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { wi = new WindowsIdentity(tokenDuplicate); wic = wi.Impersonate(); if (wic != null) { CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if (token != IntPtr.Zero) CloseHandle(token); if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate); return false; } #region IDisposable Members public void Dispose() { if(wic != null) wic.Dispose(); RevertToSelf(); } #endregion }

Version2 (desde MSDN con pequeños cambios)

class UserImpersonation2:IDisposable { [DllImport("advapi32.dll")] public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); WindowsImpersonationContext wic; IntPtr tokenHandle; string _userName; string _domain; string _passWord; public UserImpersonation2(string userName, string domain, string passWord) { _userName = userName; _domain = domain; _passWord = passWord; } const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; public bool ImpersonateValidUser() { bool returnValue = LogonUser(_userName, _domain, _passWord, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle); Console.WriteLine("LogonUser called."); if (false == returnValue) { int ret = Marshal.GetLastWin32Error(); Console.WriteLine("LogonUser failed with error code : {0}", ret); return false; } Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No")); Console.WriteLine("Value of Windows NT token: " + tokenHandle); // Check the identity. Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name); // Use the token handle returned by LogonUser. WindowsIdentity newId = new WindowsIdentity(tokenHandle); wic = newId.Impersonate(); // Check the identity. Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name); return true; } #region IDisposable Members public void Dispose() { if(wic!=null) wic.Undo(); if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); } #endregion }

Cómo usar (ambos son lo mismo)

const string file = @"//machine/test/file.txt"; using (UserImpersonation user = new UserImpersonation("user", "domain", "password")) { if (user.ImpersonateValidUser()) { StreamReader reader = new StreamReader(file); Console.WriteLine(reader.ReadToEnd()); reader.Close(); } }


a) p / invocar LogonUser con LOGON32_LOGON_NEW_CREDENTIALS y crear una nueva WindowsIdentity con el token nuevo, luego usar el acceso normal a los archivos.

b) p / invocar WNetAddConnection3 . Tenga en cuenta que esto hace que su recurso compartido remoto sea accesible para cualquier otro proceso en su máquina.

c) WMI a través de System.Management y CIM_DataFile ; ni siquiera necesitarás p / invoke. System.Management permite especificar credenciales para la máquina remota.