2009-08-12 15 views
4

Ich habe einen WCF-Webdienst erstellt, um Benutzer- und Gruppeninformationen aus Active Directory zurückzugeben. Es funktioniert für die meisten Gruppen und Benutzer.DirectoryEntry.Invoke ("groups", null) nicht alle Gruppen abrufen?

Ich benutze directoryEntry.Invoke ("Gruppen", null), um die Gruppen zurückzugeben, denen ein bestimmter Benutzer Mitglied ist. Dies gibt MOST-Gruppen zurück. Die seltsame Sache ist, dass ich eine beliebige Gruppe finden und ihre Mitglieder aufzählen kann, auch wenn es eine der Gruppen ist, die fehlt, wenn ich die Invoke-Abfrage für eines ihrer Mitglieder verwende.

Die meisten Gruppen, die dieses Verhalten aufweisen, sind Exchange-aktiviert. Die meisten problematischen Benutzerkonten sind für Benutzer in einer Verbunddomäne bestimmt, die in der von mir abgefragten Domäne einen Exchange-Server verwenden. Ich versuche nicht, Objekte in der föderierten Domäne abzufragen.

Meine Theorien so weit:

  • einige Sicherheitsbeschränkung erlauben nicht alle Gruppen über invoke Aufzählen(), obwohl ich Gruppen abfragen und aufzählen ihre Mitglieder fehlen.

  • Invoke hat Probleme mit einer Teilmenge von Gruppen. Möglicherweise werden universelle, dynamische oder Exchange-aktivierte Eigenschaften angezeigt.

  • Die Aufrufmethode erfasst nicht alle Gruppen, da die "föderierten" Konten (die im Rahmen der Exchange-Kontoeinrichtung erstellt werden) sich von normalen Domänenkonten unterscheiden über die Sid-Zuordnung zurück zu ihrer Login-Domain.

Antwort

5

Es gibt zwei bekannte Probleme bei der Verwendung der „Gruppen“ Eigenschaft auf einem Directory:

  • es wird Ihnen nicht zeigen die „Standardgruppe“ ist ein Benutzer in (in der Regel „Benutzer“)
  • es wird nicht verschachtelte Gruppe zeigt

Also, wenn ein Benutzer Mitglied einer Gruppe A, und diese Gruppe dann wiederum ist Mitglied der Gruppe B, dann in Windows-Mitgliedschaften, bedeutet dies, dass der Benutzer auch ist Mitglied von Gruppe B. Der Verzeichniseintrag zeigt jedoch nicht die Mitgliedschaft in verschachtelten Gruppen an.

Das sind die beiden einzigen Einschränkungen, die ich für Active Directory (ohne Exchange) kenne.

Die Standardgruppe ist ein wenig beteiligt, aber ich habe ein Codebeispiel dafür.

private string GetPrimaryGroup(DirectoryEntry aEntry, DirectoryEntry aDomainEntry) 
{ 
    int primaryGroupID = (int)aEntry.Properties["primaryGroupID"].Value; 
    byte[] objectSid = (byte[])aEntry.Properties["objectSid"].Value; 

    StringBuilder escapedGroupSid = new StringBuilder(); 

    // Copy over everything but the last four bytes(sub-authority) 
    // Doing so gives us the RID of the domain 
    for(uint i = 0; i < objectSid.Length - 4; i++) 
    { 
     escapedGroupSid.AppendFormat("\\{0:x2}", objectSid[i]); 
    } 

    //Add the primaryGroupID to the escape string to build the SID of the primaryGroup 
    for(uint i = 0; i < 4; i++) 
    { 
     escapedGroupSid.AppendFormat("\\{0:x2}", (primaryGroupID & 0xFF)); 
     primaryGroupID >>= 8; 
    } 

    //Search the directory for a group with this SID 
    DirectorySearcher searcher = new DirectorySearcher(); 
    if(aDomainEntry != null) 
    { 
     searcher.SearchRoot = aDomainEntry; 
    } 

    searcher.Filter = "(&(objectCategory=Group)(objectSID=" + escapedGroupSid.ToString() + "))"; 
    searcher.PropertiesToLoad.Add("distinguishedName"); 

    return searcher.FindOne().Properties["distinguishedName"][0].ToString(); 
} 

die verschachtelten Gruppen Erste nimmt auch ein paar Schritte, und ich werde zu, dass man nach einer Lösung suchen müssen, wenn das das Problem ist.

Marc

PS: als Randnotiz - warum auf der Erde tun Sie eine "DirectoryEntry.Invoke (" Gruppen "null)" nennen? Warum listen Sie nicht einfach die Eigenschaft DirectoryEntry.Properties ["memberOf"] auf, die mehrwertig ist (enthält mehrere Werte) und den DN der Gruppe (definierten Namen) enthält?

foreach(string groupDN in myUser.Properties["memberOf"]) 
{ 
    string groupName = groupDN; 
} 

ODER wenn Sie auf .NET 3.5 sind, können Sie die Verwendung der neuen Sicherheitshauptklassen in S.DS.AccountManagement machen.Eine davon ist ein "UserPrincipal", das eine Methode namens "GetAuthorizationGroups()" hat, die all diese harte Arbeit für Sie erledigt - im Prinzip kostenlos!

Sehen Sie sich eine ausgezeichnete MSDN article an, die diese neuen .NET 3.5 S.DS-Funktionen für Sie beschreibt.

+0

These sind gute Vorschläge und Sie haben Recht mit dem MSDN Artikel, ich hätte das vor dem Start gelesen. In Bezug auf den Grund, warum ich die Aufrufmethode verwendet habe, brauchte ich in diesem Fall nur die Gruppennamen, und das schien eine effiziente Möglichkeit zu sein, die Informationen zu erhalten. Ich habe nicht viel gegen Active Directory programmiert, daher lerne ich immer noch sehr gut den besten Weg, um fortzufahren. Es ist interessant, wie viel .NET sich in diesem Bereich seit 1.1 entwickelt hat! – HeathenWorld

+0

Kein Problem - nur neugierig, ob Sie einen bestimmten Grund für die Verwendung des Invoke() - Ansatzes hatten. Und hey - darum geht es bei StackOverflow - Ihnen zu helfen, wenn Sie den Wald für die Bäume nicht sehen :-) –

+0

+1 für den verlinkten MSDN Artikel, viel einfacher in 3.5 – tbone

0

Ich denke, marc_s ist korrekt. Wenn Sie alle Gruppen möchten, können Sie das folgende Snippet verwenden:

using (DirectoryEntry obj = new DirectoryEntry("LDAP://" + dn)) 
{ 
    obj.RefreshCache(new string[] { "tokenGroups" }); 
    string[] sids = new string[obj.Properties["tokenGroups"].Count]; 
    int i = 0; 
    foreach (byte[] bytes in obj.Properties["tokenGroups"]) 
    { 
     sids[i] = _ConvertSidToString(bytes); 
     ++i; 
    } 
    obj.Close(); 
    return sids; 
} 

Beachten Sie, dass verschachtelte Gruppen Berechnung ist eine teuere Operation, so Refresh eine lange Zeit in Anspruch nehmen könnte.

0

Auf Freund,

Ich versuche Verwendung des Codes und nicht immer sehr weit zu machen. Ich habe den Verzeichniseintragspfad auf "LDAP: // DC = meinDomäne, DC = co, DC = uk" aktualisiert, aber ich bekomme keine Ergebnisse (obj.Properties ["tokenGroups"].

Ich erkläre nicht, wie der Benutzer, für den die Gruppe aufgelistet werden soll, angegeben ist.

Können Sie mir bitte in die richtige Richtung zeigen?

Dank

EDIT:

Ich habe es am Ende sortiert. Der Verzeichniseintrag die Token-Gruppen zu erhalten aus sollte ein Benutzereintrag sein ... wenn das Sinn macht ...

Ich habe einige Code, falls jemand enthalten sonst die gleiche Abfrage hat:

Dim directoryEntry As DirectoryEntry = _ 
     New DirectoryEntry("LDAP://CN=users,DC=domanName,DC=com") 
Dim directorySearcher As DirectorySearcher = _ 
     New DirectorySearcher(directoryEntry, "(sAMAccountName=" & UserName & ")") 
Dim searchResult As SearchResult = directorySearcher.FindOne() 

If Not searchResult Is Nothing Then 
    Dim userDirectoryEntry As DirectoryEntry = searchResult.GetDirectoryEntry 
    userDirectoryEntry.RefreshCache(New String() {"tokenGroups"}) 
    ... etc ... 
End If