wake-up-neo.com

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

Ich verwende diesen Code, um die Gruppen des aktuellen Benutzers abzurufen. 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;
}
93
SamekaTV

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

Lesen Sie hier alles darüber: Verwalten von Directory Security Principals in .NET Framework 3.5

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

Grundsätzlich müssen Sie über einen "Hauptkontext" (normalerweise Ihre Domäne) und einen Benutzer-Principal verfügen, und dann erhalten Sie sehr einfach seine Gruppen:

public List<GroupPrincipal> GetGroups(string userName)
{
   List<GroupPrincipal> result = new List<GroupPrincipal>();

   // 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<Principal> 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 was es gibt! Sie haben nun ein Ergebnis (eine Liste) von Berechtigungsgruppen, denen der Benutzer angehört - durchlaufen, deren Namen ausdrucken oder was immer Sie tun müssen.

Update: Um auf bestimmte Eigenschaften zuzugreifen, die im UserPrincipal-Objekt nicht angezeigt werden, müssen Sie in die zugrunde liegende DirectoryEntry: Dig.

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 allzu schwer zu sein, um diese beiden Codeausschnitte zusammenzufügen .... 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;
}
144
marc_s

GetAuthorizationGroups() findet keine verschachtelten Gruppen. Um wirklich alle Gruppen zu erhalten, zu denen ein Benutzer gehört (einschließlich verschachtelter Gruppen), versuchen Sie Folgendes:

using System.Security.Principal

private List<string> GetGroups(string userName)
{
    List<string> result = new List<string>();
    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 verwende try/catch, da ich in einer sehr großen AD einige Ausnahmen mit 2 von 200 Gruppen hatte, da einige SIDs nicht mehr verfügbar waren. (Der Aufruf Translate() führt eine SID -> Namenskonvertierung durch.)

51
Mickey Mouse

Vor allem GetAuthorizationGroups () ist eine großartige Funktion, hat aber leider zwei Nachteile:

  1. Die Leistung ist schlecht, insbesondere in großen Unternehmen mit vielen Benutzern und Gruppen. Es holt viel mehr Daten, als Sie tatsächlich benötigen, und führt für jede Schleifeniteration im Ergebnis einen Serveraufruf aus
  2. Es enthält Fehler, die dazu führen können, dass Ihre Anwendung "eines Tages" nicht mehr funktioniert, wenn sich Gruppen und Benutzer weiterentwickeln. Microsoft hat das Problem erkannt und hängt mit einigen SIDs zusammen. Der Fehler, den Sie erhalten, ist "Beim Aufzählen der Gruppen ist ein Fehler aufgetreten"

Deshalb habe ich eine kleine Funktion geschrieben, um GetAuthorizationGroups () durch bessere Leistung und Fehlersicherheit zu ersetzen. Es führt nur 1 LDAP-Aufruf mit einer Abfrage mit indizierten Feldern durch. Es kann einfach 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<string> GetAdGroupsForUser2(string userName, string domainName = null)
{
    var result = new List<string>();

    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;
}
14
Bigjim

Innerhalb des AD hat jeder Benutzer eine Eigenschaft memberOf. Dies enthält eine Liste aller Gruppen, denen er angehö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<Domain>();

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<SearchResult>()
        .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);
}
}
10
Oliver

In meinem Fall konnte ich GetGroups () ohne jegliche Erledigung verwenden, indem ich den Benutzer (USER_WITH_PERMISSION) der Gruppe hinzufügte, die die Berechtigung hat, das AD (Active Directory) zu lesen. Es ist äußerst wichtig, den PrincipalContext mit diesem Benutzer und Kennwort zu erstellen.

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 "Sicherheit" die "Windows Authorization Access Group" hinzu.
  2. Klicken Sie auf die Schaltfläche "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 der ersten Gruppe die Gruppe hinzu, die Sie erstellt (übernommen) haben
1
Gandarez

Das funktioniert für mich

public string[] GetGroupNames(string domainName, string userName)
    {
        List<string> result = new List<string>();

        using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName))
        {
            using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(principalContext, userName).GetGroups())
            {
                src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
            }
        }

        return result.ToArray();
    }
0
Taran

Falls Übersetzen funktioniert lokal, aber nicht entfernt e.i group .Translate (typeof (NTAccount)

Wenn Sie möchten, dass der Anwendungscode mit der Identität LOGGED IN USER 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.

<system.web>
<identity impersonate="true"/>

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

Vielen Dank an PRAGIM Tech für diese Informationen aus seinem fleißigen Video

Windows-Authentifizierung in asp.net Part 87: 

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

Der Identitätswechsel verursacht jedoch einen erheblichen Overhead auf dem Server

Die beste Lösung, um Benutzern bestimmter Netzwerkgruppen zu erlauben, ist die anonyme Ablehnung in der Webkonfiguration <authorization><deny users="?"/><authentication mode="Windows"/>

und in Ihrem Code dahinter, vorzugsweise in global.asax, verwenden Sie 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 umgekehrten Schrägstrich geschrieben werden, d. H. "TheDomain\TheGroup".

Die Antwort hängt davon ab, welche Art von Gruppen Sie abrufen möchten. Der System.DirectoryServices.AccountManagement-Namespace bietet zwei Gruppenabrufmethoden:

GetGroups - Gibt eine Auflistung von Gruppenobjekten zurück, die die Gruppen angeben, denen der aktuelle Principal angehört.

Diese überladene Methode gibt nur die Gruppen zurück, deren Principal direkt Mitglied ist. Es werden keine rekursiven Suchen durchgeführt.

GetAuthorizationGroups - Gibt eine Auflistung von Principal-Objekten zurück, die alle Berechtigungsgruppen enthält, denen dieser Benutzer angehört. Diese Funktion gibt nur Gruppen zurück, die Sicherheitsgruppen sind. Verteilergruppen werden nicht zurückgegeben.

Diese Methode durchsucht alle Gruppen rekursiv und gibt die Gruppen zurück, in denen der Benutzer Mitglied ist. Der zurückgegebene Satz kann auch zusätzliche Gruppen enthalten, von denen das System den Benutzer zu Berechtigungszwecken als Mitglied betrachten würde. 

So erhält GetGroupsalle - Gruppen, bei denen der Benutzer ein direct -Mitglied ist, und GetAuthorizationGroups alle authorization -Gruppen, bei denen der Benutzer ein direktes oder indirektes -Mitglied ist.

Trotz ihrer Benennung ist die eine keine Untermenge der anderen. Es können Gruppen von GetGroups zurückgegeben werden, die nicht von GetAuthorizationGroups zurückgegeben werden, und umgekehrt.

Hier ist ein Anwendungsbeispiel:

PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "MyDomain", "OU=AllUsers,DC=MyDomain,DC=Local");
UserPrincipal inputUser = new UserPrincipal(domainContext);
inputUser.SamAccountName = "bsmith";
PrincipalSearcher adSearcher = new PrincipalSearcher(inputUser);
inputUser = (UserPrincipal)adSearcher.FindAll().ElementAt(0);
var userGroups = inputUser.GetGroups();
0
Tawab Wakil