2010-03-22 25 views
7

Esto se debe obtener desde una máquina remota. La siguiente consulta no funciona para SID, sino para nombres de grupos y cuentas.Tengo un SID de una cuenta de usuario y quiero los SID de los grupos a los que pertenece

"SELECT GroupComponent FROM Win32_GroupUser WHERE PartComponent = \"Win32_UserAccount.Domain='" + accountDomain + "',Name='" + accountName + "'\"" 

los objetos de Win32_Group Devuelve llegado en forma de cuerdas, y sólo tienen dominio y el nombre (a pesar de que tiene una propiedad Win32_Group SID).

tengo esta sensación de hundimiento que tendré que:

  1. Girar el SID en un nombre de cuenta mediante la consulta Win32_SID;
  2. Realice la consulta anterior;
  3. Gire cada de los nombres de grupo resultantes en SID al consultar Win32_Group.

Respuesta

3

¿Puede utilizar las clases de espacio de nombres System.DirectoryServices.AccountManagement?

using (var context = new PrincipalContext(ContextType.Domain)) 
{ 
    using (var user = UserPrincipal.FindByIdentity(context, accountName)) 
    { 
     var groups = user.GetAuthorizationGroups(); 
     ...iterate through groups and find SIDs for each one 
    } 
} 

Se debe trabajar con ContextType.Machine, aunque se necesitaría para especificar el nombre de la máquina y tienen privilegios apropiados.

using (var context = new PrincipalContext(ContextType.Machine, 
              "MyComputer", 
              userid, 
              password)) 
{ 
    ... 
} 

Hay un buen MSDN article (algo largo, sin embargo) sobre el uso del nuevo espacio de nombres .NET 3.5 cuenta de gestión.

+0

Necesito poder hacer esto también con usuarios y grupos locales. – JCCyC

+1

ContextType.Machine debe enumerar usuarios y grupos locales en la máquina especificada por nombre al crear PrincipalContext. – tvanfosson

+0

Supongo que, si me conecto a \\ MACHINENAME con WNetUseConnection() desde mpr.dll con las credenciales remotas adecuadas, debería poder obtener la información incluso si yo y la máquina remota no somos parte del mismo dominio, ¿verdad? – JCCyC

3

Sí, pero hay algunos métodos que dependen de tener un dominio.

  1. ver este page de cómo convertir un SID a un ID de usuario de P/Invoke y la API de Windows, o con .NET 2.0+ y sin P/Invoke.

    usando System.Security.Principal;

    // convertir el usuario sid a un dominio \ nombre cadena cuenta = new SecurityIdentifier (stringSid) .Translate (typeof (NTAccount)). ToString();

  2. Si tiene AD y la ID de usuario allí, entonces use the DirectorySearcher method o API de administración de cuentas para buscar los grupos. De lo contrario, utilice el método descrito en el artículo this para obtener grupos locales .

  3. Ahora usa la API sugerida por @tvanfosson para iterar los grupos y obtener los SID. O sigue la información a continuación.

En una aplicación ASP.NET es posible usar un código como este para acceder a la información de grupo siempre que un usuario sea autenticado por Windows y no por la autenticación de Formularios. En este ejemplo he dejado una nota interesante acerca de las excepciones que se tiran en ese ambiente pero puede aplicarse a otros usuarios:

public List<string> GetGroupsFromLogonUserIdentity() 
{ 
    List<string> groups = new List<string>(); 
    HttpRequest request = HttpContext.Current.Request; 

    if (request.LogonUserIdentity.Groups != null) 
    { 
     foreach (IdentityReference group in request.LogonUserIdentity.Groups) 
     { 
      try 
      { 
       groups.Add(group.Translate(typeof(NTAccount)).ToString()); 
      } 
      catch (IdentityNotMappedException) 
      { 
       // Swallow these exceptions without throwing an error. They are 
       // the result of dead objects in AD which are associated with 
       // user accounts. In this application users may have a group 
       // name associated with their AD profile which cannot be 
       // resolved in the Active Directory. 
      } 
     } 
    } 

    return groups; 
} 

LogonUserIdentity se basa en la clase WindowsIdentity. Puede modificar mi ejemplo de código para usar WindowsIdentity y funcionar en una aplicación que no sea Web.Una vez que itere sobre un grupo, debería poder hacer algo como esto para obtener SecurityIdentifier:

SecurityIdentifier secid = group as SecurityIdentifier; 
Cuestiones relacionadas