Cómo utilizar componentes nativos de ADSI para encontrar el grupo principal

Resumen

Este artículo explica cómo utilizar componentes nativos de Active Directory Services Interface (ADSI) para determinar la pertenencia al grupo principal de un usuario.

Más información

Cómo se almacena el grupo principal de un objeto de usuario en Active Directory

Cada objeto de contexto de seguridad (como usuarios y grupos de seguridad) en Active Directory tiene un atributo de identificador (SID) de seguridad asociado a él. El SID tiene varios componentes, como se describe en la referencia de "Componentes de SID" incluida en la sección "Referencia" de este artículo. Dos de estos componentes en el SID son el identificador relativo (RID) de dominio y la específica RID al objeto dentro del dominio.

El grupo principal de un usuario se almacena (como RID del grupo en el dominio del usuario) en el atributo PrimaryGroupID de un objeto de usuario. Grupo principal de un usuario sólo puede ser un grupo que existe en el mismo dominio que el usuario, y este grupo tiene que ser un grupo en el que el usuario es un miembro de. Además, este objeto de grupo en Active Directory tiene un atributo denominado PrimaryGroupToken, que almacena el RID para este grupo en el dominio.

Los proveedores de Windows NT y Protocolo ligero de acceso a directorios (LDAP) permiten a los programadores cambiar el grupo principal de un usuario al establecer el valor del atributo PrimaryGroupID en el RID de un grupo en el que el usuario es un miembro de. Si el usuario no es miembro de un grupo, no puede establecer el usuario PrimaryGroupID el RID del grupo.

Cuando utiliza el proveedor de Windows NT en ADSI, el grupo principal se incluye como una entrada en la colección de IADsUser::Groups del usuario.

Con el proveedor LDAP, el grupo principal es no incluir como una entrada en la colección IADsUser::Groups , ni es parte de nombre completo (DN) del grupo del atributo MemberOf del objeto de usuario en el directorio. RID del grupo en PrimaryGroupID es el único lugar en el que el grupo principal de un usuario se hace referencia en el objeto de usuario LDAP.

Ningún proveedor define un mecanismo para determinar el nombre del grupo principal de un usuario directamente desde sus objetos de usuario respectivos. El problema se hace aún más complejo por el hecho de que cada objeto de grupo proporcionado por cada proveedor es compatible con un conjunto diferente de atributos, como sigue:

  • El objeto de grupo proporcionado por Windows NT no admite el atributo PrimaryGroupToken ni el proveedor de Windows NT es compatible con cualquier otra forma de recuperar RID del grupo mediante código nativo de ADSI.
  • El atributo PrimaryGroupToken de un objeto de grupo de proveedor LDAP es un atributo calculado. Este atributo no existe en el objeto de grupo en el directorio. De hecho, es, crea el atributo cuando lo solicite el cliente con una llamada al método de IADs::GetInfoEx . No es posible realizar búsquedas LDAP basadas en atributos construidos en Active Directory. Por lo tanto, no puede buscar mediante el proveedor LDAP para un grupo basado en el atributo PrimaryGroupToken que coincide con el atributo PrimaryGroupID en el objeto de usuario cuyo grupo principal desea determinar. Esto también descarta una solución pura de ADSI que no es dependiente de un objeto COM externo para ayudarle a determinar el grupo principal.

Formas de determinar el grupo principal de un usuario

Los siguientes son tres métodos conocidos para determinar el nombre del grupo principal de un usuario:

  • Generar a un SID de cadena de enlace para el objeto de grupo en Active Directory desde el componente de dominio RID del SID del usuario y RID del grupo almacenado en el atributo PrimaryGroupID del objeto de usuario.

    Éste es el método que se describe en artículo de Microsoft KB Q297951 (incluido en la sección "Referencia" de este artículo). El problema principal con este método es que para generar al SID de cadena de enlace, el programador debe confiar en el objeto ADsSID para convertir el descriptor de seguridad binario del objeto de dominio en su formato SDDL. El objeto ADsSID está alojado en el archivo ADsSecurity.dll, que se debe copiar a y registrado en el cliente antes de que el código se puede ejecutar correctamente.
  • Utilizar una consulta LDAP para buscar todos los grupos de un dominio y devolver su atributo PrimaryGroupToken .

    Este método es una solución pura de LDAP. Sin embargo, la solución mediante secuencias de comandos no es muy eficaz porque esta búsqueda devuelve todos los grupos en el dominio, incluso aquellos que el usuario no es miembro de; y ya que el atributo PrimaryGroupToken se construye en el cliente mientras se recorre el conjunto de registros, esta búsqueda es bastante lenta. Este método puede ser especialmente lento si hay un gran número de grupos en el dominio. Abundan los ejemplos de cómo crear consultas de ADO de dialecto LDAP y, por tanto, no se incluyen en este artículo.
  • Aprovechar las características de cada proveedor para crear una solución híbrida.

    Esta solución aprovecha las ventajas de las características de los diferentes proveedores para determinar el grupo principal del usuario. Para ello, siga estos pasos:
    1. Enlazar con el objeto de usuario con el proveedor de Windows NT.

      El objeto de usuario de Windows NT proporciona una colección de grupos que se garantiza que contenga el grupo principal del usuario. Además, PrimaryGroupID del objeto de usuario se almacena inmediatamente en una ubicación temporal para su uso posterior en este algoritmo.
    2. Enumerar la colección IADsUser::Groups .
    3. Extraer la propiedad SamAccountName de ADsPath para cada grupo de esta colección y, a continuación, generar una cadena de consulta de dialecto LDAP para buscar todos los grupos con la propiedad SamAccountName enumerada en esta colección, para devolver los valores de atributo PrimaryGroupToken y DistinguishedName .
    4. Ejecutar la búsqueda de ADSI de ADO y, a continuación, recorrer el conjunto de registros de cada grupo PrimaryGroupToken de comparar con el valor del atributo PrimaryGroupID almacenado previamente.
    5. Si encuentra a una coincidencia, detener y mostrar el nombre completo de este grupo como el grupo primario para este usuario.
    6. Si no encuentra a una coincidencia, continúe recorriendo el resultado de la búsqueda.
    Las ventajas de este método son evidentes de inmediato. Todos los objetos que se utilizan son nativos de ADSI y no requieren componentes adicionales. Además, la enumeración incluye solamente aquellos grupos que podrían ser el grupo principal.

    Sin embargo, tenga en cuenta la desventaja siguiente: cuando se enumera la colección IADsUser::Groups , el objeto devuelto es una interfaz IADs para los miembros del grupo. Si, por alguna razón, el usuario que realiza la enumeración no tiene los permisos necesarios para abrir un objeto en particular, la enumeración se detiene sin indicar un error. El código siguiente muestra cómo puede implementar el algoritmo anterior:

    dim oUsr dim oGrp 

    '
    ' ToDo: Change the following variables to specific values for your domain.
    '
    DomainName = "myDomain"
    UserLoginName = "myUserLoginName"

    '
    ' Bind to the user object with the Windows NT provider.
    '
    set oUsr = GetObject("WinNT://" & DomainName & "/" & UserLoginName & ",user")
    set grp = oUsr.Groups
    GrpID = oUsr.PrimaryGroupID
    GrpName = ""

    '
    ' Building Query Filter for the search for all the groups that the user is a member of.
    '
    QueryFilter = "(|"
    for each Item in Grp
    NT4Name = replace(Item.ADsPath,"WinNT://","")
    tempArray = split(nt4Name,"/")
    NT4Name = tempArray(1)
    QueryFilter = QueryFilter & "(samAccountName=" & NT4Name & ")"
    next
    QueryFilter = QueryFilter & ")"

    '
    ' Building LDAP dialect Query String.
    '
    QueryString = "<LDAP://" & DomainName & ">;" & QueryFilter & ";PrimaryGroupToken,distinguishedName;subtree"

    '
    ' Performing Query against the Active Directory for all the groups that
    ' the user belongs to and retrieving the RID of the group object off
    ' the PrimaryGroupToken attribute on the user.
    '
    Dim oConnection, oCommand, oRecordset
    Set oConnection = CreateObject("ADODB.Connection")
    Set oCommand = CreateObject("ADODB.Command")

    oConnection.Provider = "ADsDSOObject"
    oConnection.Open "Active Directory Provider"

    Set oCommand.ActiveConnection = oConnection
    oCommand.CommandText = QueryString
    oCommand.Properties("Page Size") = 900

    Set oRecordset = oCommand.Execute

    '
    ' Looping through all the records in the search result to determine whether
    ' any of these group's PrimaryGroupToken attribute value match the
    ' PrimaryGroupID attribute value stored on the user object.
    '
    While ((NOT oRecordset.EOF) and (Not bGroupFound))
    if (GrpID = oRecordset.Fields("PrimaryGroupToken").value) then
    GrpName = oRecordset.Fields("DistinguishedName").Value
    bGroupFound = True
    End If
    oRecordset.moveNext
    Wend

    Set oRecordset = Nothing
    Set oCommand = Nothing
    Set oConnection = Nothing

    '
    ' Displaying Results of the search.
    '
    if( bGroupFound ) then
    WScript.Echo "Primary Group for " & oUsr.AdsPath
    WScript.Echo "Is: " & GrpName
    else
    WScript.Echo "Primary Group Not Found"
    end if

Referencias

Para obtener más información, haga clic en el siguiente número de artículo para verlo en Microsoft Knowledge Base:

297951 cómo utilizar el atributo PrimaryGroupID para buscar el grupo principal de un usuario

Propiedades

Id. de artículo: 321360 - Última revisión: 17 ene. 2017 - Revisión: 1

Comentarios