Este artigo explica como utilizar nativo componentes de interface de serviços do Active Directory (ADSI) para determinar os membros do grupo primário de um utilizador.
Como o grupo primário é armazenado num objecto de utilizador no Active Directory
Cada objecto de contexto de segurança (tais como utilizadores e grupos de segurança) no Active Directory tem um atributo de identificador de segurança (SID) de segurança associado. O SID tem vários componentes, conforme descrito a referência "Componentes do SID" incluída na secção "Referências" deste artigo. Dois destes componentes no SID são o identificador de domínio relativo (RID) e o específico RID para o objecto dentro do domínio.
O grupo primário de um utilizador é armazenado (como RID o grupo no domínio do utilizador) no atributo
PrimaryGroupID de um objecto de utilizador. Grupo primário do utilizador só pode ser um grupo existente no mesmo domínio que o utilizador e este grupo tem de ser um grupo que o utilizador for membro de. Além disso, este objecto de
grupo no Active Directory tem um atributo denominado
PrimaryGroupToken , que armazena o RID para este grupo no domínio.
Fornecedores de Windows NT e (LIGHTWEIGHT Directory Access Protocol) permitem aos programadores transformar o grupo primário do utilizador, definindo o valor do atributo
PrimaryGroupID como o RID de um grupo que o utilizador é membro do. Se o utilizador não for membro de um grupo,
PrimaryGroupID o utilizador Impossível definir o RID, RELATIVE do grupo.
Quando utiliza o fornecedor de Windows NT em ADSI, o grupo primário é incluído como uma entrada na colecção de
IADsUser::Groups do utilizador.
Com o fornecedor LDAP, o grupo primário é
não incluído como uma entrada na colecção
IADsUser::Groups nem é parte do nome distinto (DN) do grupo do atributo
membro do objecto de utilizador no directório. RID o grupo no
PrimaryGroupID é o local apenas no qual o grupo primário para um utilizador é referenciado no objecto de utilizador LDAP.
Nenhum fornecedor define um mecanismo para determinar o nome do grupo primário para um utilizador directamente os objectos de utilizador respectiva. O problema for feito ainda mais complexo o facto de que cada objecto de grupo fornecido por cada fornecedor suporta um conjunto de atributos, diferente da seguinte forma:
- O objecto de grupo fornecidos pelo Windows NT não suporta o atributo PrimaryGroupToken nem o fornecedor de Windows NT suporta qualquer outra forma de obter RID o grupo utilizando código ADSI nativo.
- O atributo PrimaryGroupToken de um fornecedor de grupo de objectos do LDAP é um atributo calculado. Este atributo não existe no objecto de grupo no directório. O atributo é, na realidade, criado quando é pedida pelo cliente com uma chamada de método IADs::GetInfoEx . Não é possível efectuar procuras LDAP com base nos atributos construídos no Active Directory. Por conseguinte, não pode procurar utilizando o fornecedor LDAP para um grupo com base no atributo PrimaryGroupToken que corresponda o atributo PrimaryGroupID no objecto de utilizador cujo grupo primário que deseja determinar. Também regras sem uma solução ADSI pura, que não está dependente de um objecto COM externo para o ajudar a determinar o grupo primário.
Formas de determinar o grupo primário de um utilizador
Seguem-se três métodos para determinar o nome do grupo primário de um utilizador conhecidos:
- Crie um SID cadeia de ligação para o objecto de grupo no Active Directory do componente de RID do domínio do SID do utilizador e RID do grupo armazenados no atributo PrimaryGroupID no objecto de utilizador.
Este é o método descrito no artigo da Microsoft KB Q297951 (incluído na secção "Referências" deste artigo). O principal problema com este método é que para criar o SID cadeia de ligação, o programador tem dependem do objecto ADsSID para converter o descritor de segurança binário do objecto de domínio em formato SDDL. O objecto ADsSID hospedado o ficheiro ADsSecurity.dll, que deve ser copiado para e registado no cliente antes do código pode ser executado com êxito. - Utilize uma consulta LDAP para procurar todos os grupos de um domínio e devolver o respectivo atributo PrimaryGroupToken .
Este método é uma solução LDAP pura. No entanto, a solução de scripts não é muito eficiente porque esta procura irá devolver cada grupo no domínio, mesmo aqueles que o utilizador não é um membro do; e uma vez que o atributo PrimaryGroupToken é construído no cliente como o conjunto de registos é partilhado, esta procura é muito lenta. Este método pode ser particularmente demorado se houver um grande número de grupos no domínio. Exemplos de como criar consultas de ADO LDAP dialecto abound e por este motivo, não são incluídas neste artigo. - Tirar partido das funcionalidades do cada fornecedor para criar uma solução híbrida.
Esta solução tira partido das funcionalidades dos diferentes fornecedores para determinar o grupo primário do utilizador. Para o fazer, siga estes passos:- Ligar o objecto de utilizador com o fornecedor de Windows NT.
O objecto de utilizador de Windows NT fornece uma colecção de grupo é garantido que contêm o grupo primário do utilizador. Além disso, PrimaryGroupID do objecto de utilizador é armazenado fora do escritório numa localização temporária para utilização posterior este algoritmo. - Enumere a colecção IADsUser::Groups .
- Extrair a propriedade SamAccountName do ADsPath para cada grupo desta colecção e, em seguida, criar uma cadeia de consulta LDAP dialecto para procurar todos os grupos com a propriedade SamAccountName listada nesta colecção, devolver os valores de atributo PrimaryGroupToken e DistinguishedName .
- Executar a procura ADSI ADO e, em seguida, repetir através de conjunto de registos, comparar PrimaryGroupToken cada grupo com o valor de atributo PrimaryGroupID anteriormente colocado em cache.
- Se encontrar uma correspondência, pare e apresentar o nome distinto para este grupo como o grupo primário para este utilizador.
- Se não encontrar uma correspondência, continue ciclo através do resultado da procura.
As vantagens deste método são óbvias imediatamente. Todos os objectos utilizados são nativos do ADSI e não necessitam de componentes adicionais. Além disso, a enumeração inclui apenas os grupos que poderão ser o grupo primário.
No entanto, tenha em atenção a desvantagem seguinte: quando é enumerada a colecção IADsUser::Groups , o objecto devolvido é uma interface IADs para o membro do grupo. Se, por alguma razão, o utilizador executar a enumeração não tiver as permissões necessárias para abrir um determinado objecto, pára a enumeração sem indicar um erro. O seguinte código ilustra como pode implementar o 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
Para obter mais informações, clique no número de artigo que se segue para visualizar o artigo na Microsoft Knowledge Base:
297951
(http://support.microsoft.com/kb/297951/
)
Como utilizar o atributo PrimaryGroupID para localizar o grupo primário de um utilizador