c# - los - permisos de usuario windows 7
Enumerar miembros del grupo de usuarios de Windows en un sistema remoto usando c# (5)
Dentro de c #, necesito poder
- Conéctese a un sistema remoto, especificando nombre de usuario / contraseña según corresponda
- Enumera los miembros de un grupo local en ese sistema
- Obtener los resultados de vuelta a la computadora de ejecución
Así que, por ejemplo, me conectaría con / SOMESYSTEM con las credenciales adecuadas y recuperaré una lista de administradores locales, incluido SOMESYSTEM / Administrator, SOMESYSTEM / Bob, DOMAIN / AlanH, "DOMAIN / Domain Administrators".
Intenté esto con system.directoryservices.accountmanagement, pero tengo problemas con la autenticación. A veces tengo:
No se permiten múltiples conexiones a un servidor o recurso compartido por el mismo usuario, que usa más de un nombre de usuario. Desconecte todas las conexiones previas al servidor o recurso compartido y vuelva a intentarlo. (Excepción de HRESULT: 0x800704C3)
Lo anterior está intentando porque habrá situaciones en las que simplemente no puedo desasignar unidades existentes o conexiones UNC.
Otras veces, mi programa recibe error desconocido y el registro de seguridad en el sistema remoto informa un error 675, código 0x19 que es KDC_ERR_PREAUTH_REQUIRED.
¡Necesito una manera más simple y menos propensa a errores para hacer esto!
Debería poder hacer esto con System.DirectoryServices.DirectoryEntry. Si tiene problemas para ejecutarlo de manera remota, tal vez podría instalar algo en las máquinas remotas para darle sus datos a través de algún tipo de RPC, como la comunicación remota o un servicio web. Pero creo que lo que estás intentando debería ser posible de forma remota sin ser demasiado elegante.
Esto debería ser fácil de hacer usando WMI. Aquí tienes un puntero a algunos documentos:
Documentación de WMI para Win32_UserAccount
Incluso si no tiene experiencia previa con WMI, debería ser bastante fácil convertir ese código de VB Script en la parte inferior de la página en algún código .NET.
Espero que esto haya ayudado!
Si Windows no le permite conectarse a través de su mecanismo de inicio de sesión, creo que su única opción es ejecutar algo en la máquina remota con un puerto abierto (ya sea directamente o mediante comunicación remota o un servicio web, como se mencionó).
Yo recomendaría usar la función API de Win32 NetLocalGroupGetMembers . Es mucho más sencillo que tratar de descubrir la sintaxis de LDAP loca, que es necesaria para algunas de las otras soluciones que se recomiendan aquí. Siempre que se haga pasar por el usuario al que desea ejecutar el control llamando a "Usuario de inicio de sesión", no debería encontrarse con ningún problema de seguridad.
Puede encontrar un código de muestra para hacer la suplantación aquí .
Si necesita ayuda para averiguar cómo llamar a "NetLocalGroupGetMembers" desde C #, le recomiendo que consulte al asistente de PInvoke de Jared Parson, que puede descargar desde Codeplex.
Si está ejecutando el código en una aplicación ASP.NET que se ejecuta en IIS y desea suplantar al usuario que accede al sitio web para realizar la llamada, es posible que deba otorgar permiso "Confiable para la delegación" al servidor web de producción.
Si está ejecutando en el escritorio, entonces el uso de las credenciales de seguridad del usuario activo no debería ser un problema.
Es posible que el administrador de la red haya revocado el acceso al "Objeto securable" para la máquina particular a la que está intentando acceder. Lamentablemente, el acceso es necesario para que funcionen todas las funciones de API de gestión de red . Si ese es el caso, entonces deberá otorgar acceso al "Objeto Securable" para los usuarios que desee ejecutar. Sin embargo, con la configuración de seguridad predeterminada de Windows, todos los usuarios autenticados deberían tener acceso.
Espero que esto ayude.
-Scott
davidg estaba en el camino correcto, y le estoy acreditando la respuesta.
Pero la consulta WMI necesaria era un poco menos directa, ya que no solo necesitaba una lista de usuarios para toda la máquina, sino también el subconjunto de usuarios y grupos , ya fueran locales o de dominio, que eran miembros del grupo Administradores local. Para el registro, esa consulta WMI fue:
SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = "Win32_Group.Domain=''thehostname'',Name=''thegroupname''"
Aquí está el fragmento de código completo:
public string GroupMembers(string targethost, string groupname, string targetusername, string targetpassword)
{
StringBuilder result = new StringBuilder();
try
{
ConnectionOptions Conn = new ConnectionOptions();
if (targethost != Environment.MachineName) //WMI errors if creds given for localhost
{
Conn.Username = targetusername; //can be null
Conn.Password = targetpassword; //can be null
}
Conn.Timeout = TimeSpan.FromSeconds(2);
ManagementScope scope = new ManagementScope("////" + targethost + "//root//cimv2", Conn);
scope.Connect();
StringBuilder qs = new StringBuilder();
qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = /"Win32_Group.Domain=''");
qs.Append(targethost);
qs.Append("'',Name=''");
qs.Append(groupname);
qs.AppendLine("''/"");
ObjectQuery query = new ObjectQuery(qs.ToString());
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
ManagementPath path = new ManagementPath(m["PartComponent"].ToString());
{
String[] names = path.RelativePath.Split('','');
result.Append(names[0].Substring(names[0].IndexOf("=") + 1).Replace("/"", " ").Trim() + "//");
result.AppendLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace("/"", " ").Trim());
}
}
return result.ToString();
}
catch (Exception e)
{
Console.WriteLine("Error. Message: " + e.Message);
return "fail";
}
}
Entonces, si invoca Groupmembers ("Server1", "Administrators", "myusername", "mypassword"); Recibo una sola cadena devuelta con:
SERVER1 / Administrador
MYDOMAIN / Administradores del dominio
El retorno real de WMI es más como esto:
// SERVER1 / root / cimv2: Win32_UserAccount.Domain = "SERVER1", Name = "Administrador"
... así que como pueden ver, tuve que hacer una pequeña manipulación de cuerdas para arreglarlo.