Wie bekomme ich die Gruppen eines Benutzers in Active Directory? (c #, asp.net)

Ich benutze diesen Code, um die Gruppen des aktuellen Benutzers zu erhalten. Aber ich möchte den Benutzer manuell geben und dann seine Gruppen bekommen. Wie kann ich das machen?

using System.Security.Principal; public ArrayList Groups() { ArrayList groups = new ArrayList(); foreach (IdentityReference group in System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups) { groups.Add(group.Translate(typeof(NTAccount)).ToString()); } return groups; } 

Wenn Sie .NET 3.5 oder höher verwenden, können Sie den neuen System.DirectoryServices.AccountManagement (S.DS.AM) -Namespace verwenden, der dies viel einfacher macht als früher.

Lesen Sie alles darüber: Verwalten von Verzeichnissicherheitsprinzipalen in .NET Framework 3.5

Update: Ältere Artikel des MSDN-Magazins sind leider nicht mehr online – Sie müssen das CHM für das MSDN-Magazin vom Januar 2008 von Microsoft herunterladen und den Artikel dort lesen.

Im Grunde brauchen Sie einen “Hauptkontext” (in der Regel Ihre Domäne), einen Benutzerprinzipal, und Sie erhalten dann sehr einfach seine Gruppen:

 public List GetGroups(string userName) { List result = new List(); // establish domain context PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain); // find your user UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, userName); // if found - grab its groups if(user != null) { PrincipalSearchResult groups = user.GetAuthorizationGroups(); // iterate over all groups foreach(Principal p in groups) { // make sure to add only group principals if(p is GroupPrincipal) { result.Add((GroupPrincipal)p); } } } return result; } 

und das ist alles! Sie haben jetzt ein Ergebnis (eine Liste) von Autorisierungsgruppen, zu denen der Benutzer gehört – über sie iterieren, ihre Namen ausdrucken oder was immer Sie tun müssen.

Update: Um auf bestimmte Eigenschaften zugreifen zu können, die nicht auf dem UserPrincipal Objekt aufgetaucht sind, müssen Sie in den zugrunde liegenden DirectoryEntry UserPrincipal :

 public string GetDepartment(Principal principal) { string result = string.Empty; DirectoryEntry de = (principal.GetUnderlyingObject() as DirectoryEntry); if (de != null) { if (de.Properties.Contains("department")) { result = de.Properties["department"][0].ToString(); } } return result; } 

Update # 2: scheint nicht zu schwer zu sein, diese zwei Code-Schnipsel zusammen zu setzen …. aber ok – hier geht es:

 public string GetDepartment(string username) { string result = string.Empty; // if you do repeated domain access, you might want to do this *once* outside this method, // and pass it in as a second parameter! PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain); // find the user UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, username); // if user is found if(user != null) { // get DirectoryEntry underlying it DirectoryEntry de = (user.GetUnderlyingObject() as DirectoryEntry); if (de != null) { if (de.Properties.Contains("department")) { result = de.Properties["department"][0].ToString(); } } } return result; } 

GetAuthorizationGroups() findet verschachtelte Gruppen nicht. Um wirklich alle Gruppen zu erhalten, denen ein bestimmter Benutzer angehört (einschließlich verschachtelter Gruppen), versuchen Sie Folgendes:

 using System.Security.Principal private List GetGroups(string userName) { List result = new List(); WindowsIdentity wi = new WindowsIdentity(userName); foreach (IdentityReference group in wi.Groups) { try { result.Add(group.Translate(typeof(NTAccount)).ToString()); } catch (Exception ex) { } } result.Sort(); return result; } 

Ich benutze try/catch weil ich einige Ausnahmen mit 2 von 200 Gruppen in einem sehr großen AD hatte, weil einige SIDs nicht mehr verfügbar waren. (Der Translate() Aufruf führt eine SID -> Namenskonvertierung durch.)

Zunächst einmal ist GetAuthorizationGroups () eine großartige function, hat aber leider zwei Nachteile:

  1. Die performance ist schlecht, besonders in großen Unternehmen mit vielen Benutzern und Gruppen. Es ruft viel mehr Daten ab, die Sie tatsächlich benötigen, und ruft für jede Schleifeniteration im Ergebnis einen Serveraufruf ab
  2. Es enthält Fehler, die dazu führen können, dass Ihre Anwendung irgendwann nicht mehr funktioniert, wenn sich Gruppen und Benutzer weiterentwickeln. Microsoft hat das Problem erkannt und ist mit einigen SIDs verknüpft. Der Fehler, den Sie erhalten, ist “Beim Auflisten der Gruppen ist ein Fehler aufgetreten”

Daher habe ich eine kleine function geschrieben, um GetAuthorizationGroups () durch bessere performance und Fehlersicherheit zu ersetzen. Es führt nur einen LDAP-Aufruf mit einer Abfrage über indizierte Felder aus. Es kann leicht erweitert werden, wenn Sie mehr Eigenschaften als nur die Gruppennamen benötigen (Eigenschaft “cn”).

 // Usage: GetAdGroupsForUser2("domain\user") or GetAdGroupsForUser2("user","domain") public static List GetAdGroupsForUser2(string userName, string domainName = null) { var result = new List(); if (userName.Contains('\\') || userName.Contains('/')) { domainName = userName.Split(new char[] { '\\', '/' })[0]; userName = userName.Split(new char[] { '\\', '/' })[1]; } using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, domainName)) using (UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, userName)) using (var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domainContext.Name))) { searcher.Filter = String.Format("(&(objectCategory=group)(member={0}))", user.DistinguishedName); searcher.SearchScope = SearchScope.Subtree; searcher.PropertiesToLoad.Add("cn"); foreach (SearchResult entry in searcher.FindAll()) if (entry.Properties.Contains("cn")) result.Add(entry.Properties["cn"][0].ToString()); } return result; } 

Innerhalb der AD hat jeder Benutzer eine Eigenschaft memberOf . Dieser enthält eine Liste aller Gruppen, zu denen er gehört.

Hier ist ein kleines Codebeispiel:

 // (replace "part_of_user_name" with some partial user name existing in your AD) var userNameContains = "part_of_user_name"; var identity = WindowsIdentity.GetCurrent().User; var allDomains = Forest.GetCurrentForest().Domains.Cast(); var allSearcher = allDomains.Select(domain => { var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domain.Name)); // Apply some filter to focus on only some specfic objects searcher.Filter = String.Format("(&(&(objectCategory=person)(objectClass=user)(name=*{0}*)))", userNameContains); return searcher; }); var directoryEntriesFound = allSearcher .SelectMany(searcher => searcher.FindAll() .Cast() .Select(result => result.GetDirectoryEntry())); var memberOf = directoryEntriesFound.Select(entry => { using (entry) { return new { Name = entry.Name, GroupName = ((object[])entry.Properties["MemberOf"].Value).Select(obj => obj.ToString()) }; } }); foreach (var item in memberOf) { Debug.Print("Name = " + item.Name); Debug.Print("Member of:"); foreach (var groupName in item.GroupName) { Debug.Print(" " + groupName); } Debug.Print(String.Empty); } } 

In meinem Fall war der einzige Weg, wie ich GetGroups () ohne Expose weiter verwenden konnte, das Hinzufügen des Benutzers (USER_WITH_PERMISSION) zu der Gruppe, die die Berechtigung zum Lesen des AD (Active Directory) hat. Es ist äußerst wichtig, den PrincipalContext zu erstellen, der diesen Benutzer und das Passwort übergibt.

 var pc = new PrincipalContext(ContextType.Domain, domain, "USER_WITH_PERMISSION", "PASS"); var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, userName); var groups = user.GetGroups(); 

Schritte, die Sie in Active Directory ausführen können, damit es funktioniert:

  1. Erstellen Sie in Active Directory eine Gruppe (oder nehmen Sie eine) und fügen Sie auf der Registerkarte “secutiy” die Option “Windows Authorization Access Group” hinzu.
  2. Klicken Sie auf “Erweitert”
  3. Wählen Sie “Windows Authorization Access Group” und klicken Sie auf “View”
  4. Aktivieren Sie “Read tokenGroupsGlobalAndUniversal”
  5. Suchen Sie den gewünschten Benutzer und fügen Sie ihn zu der Gruppe hinzu, die Sie im ersten Schritt erstellt (übernommen) haben

Falls Translate lokal arbeitet, aber nicht remotely ei group. Übersetzen (typeof (NTAccount)

Wenn Sie möchten, dass der Anwendungscode mit der LOGGED IN USER-Identität ausgeführt wird, aktivieren Sie den Identitätswechsel. Identitätswechsel kann durch IIS oder durch Hinzufügen des folgenden Elements in der web.config aktiviert werden .

   

Wenn der Identitätswechsel aktiviert ist, wird die Anwendung mit den Berechtigungen ausgeführt, die in Ihrem Benutzerkonto gefunden wurden. Wenn der angemeldete Benutzer Zugriff auf eine bestimmte Netzwerkressource hat, ist er nur dann in der Lage, über die Anwendung auf diese Ressource zuzugreifen.

Danke PRAGIM Tech für diese Information von seinem fleißigen Video

Windows-Authentifizierung in asp.net Teil 87:

https://www.youtube.com/watch?v=zftmaZ3ySMc

Aber Identitätswechsel erzeugt eine Menge Aufwand auf dem Server

Die beste Lösung, um Benutzern bestimmter Netzwerkgruppen zu erlauben, besteht darin, in der Webkonfiguration anonym zu verweigern

und in Ihrem Code hinter, vorzugsweise in der global.asax, verwenden Sie die HttpContext.Current.User.IsInRole :

 Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) If HttpContext.Current.User.IsInRole("TheDomain\TheGroup") Then //code to do when user is in group End If 

HINWEIS: Die Gruppe muss mit einem Backslash \ ie “TheDomain \ TheGroup” geschrieben werden

Das funktioniert für mich

 public string[] GetGroupNames(string domainName, string userName) { List result = new List(); using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName)) { using (PrincipalSearchResult src = UserPrincipal.FindByIdentity(principalContext, userName).GetGroups()) { src.ToList().ForEach(sr => result.Add(sr.SamAccountName)); } } return result.ToArray(); }