it-swarm.com.de

C # Active Directory: Domänennamen des Benutzers abrufen?

Ich weiß, dass diese Art von Frage schon einmal gestellt wurde, aber andere Methoden versagen mir im Moment.

So wie es aussieht, fragt unser Windows-Dienst AD nach einem LDAP (dh LDAP: //10.32.16.80) und einer Liste von Benutzergruppen innerhalb dieses AD-Servers ab, nach denen gesucht werden soll .. _ Er ruft alle Benutzer innerhalb der angegebenen Gruppen auf und rekursiv nach diesen Gruppen für weitere Gruppen ebenfalls ... Jeder Benutzer wird dann zu einer Liste der authentifizierten Benutzer einer anderen Anwendung hinzugefügt.

Dieser Teil der Anwendung wird erfolgreich ausgeführt. Wir benötigen jedoch den freundlichen Domänennamen jedes Benutzers (d. H. Den Teil seines Login-Domains/Benutzername).

Wenn es also einen Benutzer gibt, der Teil der TEST-Domäne ist, heißt Steve: TEST/steve ist sein Login .. Ich kann steve in der AD finden, jedoch brauche ich auch "TEST", um mit ihm gespeichert zu werden AD-Informationen.

Auch hier kann ich "steve" gut finden, indem ich einen Verzeichnis-Sucher und die LDAP-IP-Adresse verwende, aber wenn ich die LDAP-IP-Adresse benutze, wie kann ich dann den freundlichen Domänennamen finden?

Wenn ich den folgenden Code versuche, wird beim Versuch, auf "defaultNamingContext" zuzugreifen, eine Fehlermeldung angezeigt:

System.Runtime.InteropServices.COMException (0x8007202A): Der Authentifizierungsmechanismus ist unbekannt.

Hier ist der Code:

    private string SetCurrentDomain(string server)
    {
        string result = string.Empty;
        try
        {
            logger.Debug("'SetCurrentDomain'; Instantiating rootDSE LDAP");
            DirectoryEntry ldapRoot = new DirectoryEntry(server + "/rootDSE", username, password);
            logger.Debug("'SetCurrentDomain'; Successfully instantiated rootDSE LDAP");

            logger.Debug("Attempting to retrieve 'defaultNamingContext'...");
            string domain = (string)ldapRoot.Properties["defaultNamingContext"][0]; //THIS IS WHERE I HIT THE COMEXCEPTION
            logger.Debug("Retrieved 'defaultNamingContext': " + domain);
            if (!domain.IsEmpty())
            {

                logger.Debug("'SetCurrentDomain'; Instantiating partitions/configuration LDAP entry");
                DirectoryEntry parts = new DirectoryEntry(server + "/CN=Partitions,CN=Configuration," + domain, username, password);

                logger.Debug("'SetCurrentDomain'; Successfully instantiated partitions/configuration LDAP entry");
                foreach (DirectoryEntry part in parts.Children)
                {
                    if (part.Properties["nCName"] != null && (string)part.Properties["nCName"][0] != null)
                    {
                        logger.Debug("'SetCurrentDomain'; Found property nCName");
                        if ((string)part.Properties["nCName"][0] == domain)
                        {
                            logger.Debug("'SetCurrentDomain'; nCName matched defaultnamingcontext");
                            result = (string)part.Properties["NetBIOSName"][0];
                            logger.Debug("'SetCurrentDomain'; Found NetBIOSName (friendly domain name): " + result);
                            break;
                        }
                    }
                }
            }
            logger.Debug("finished setting current domain...");
        }
        catch (Exception ex)
        {
            logger.Error("error attempting to set domain:" + ex.ToString());
        }
        return result;
    }

bearbeiten

Ich habe diese Beispielmethode hinzugefügt, um einen Vorschlag zu versuchen, erhalte jedoch eine Ausnahme: "Nicht angegebener Fehler", wenn ich den Aufruf "FindAll ()" im Sucher stelle .. .. Die übergebene Zeichenfolge lautet: "CN = TEST USER" , CN = Benutzer, DC = Tempe, DC = ktregression, DC = com "

        private string GetUserDomain(string dn)
    {
        string domain = string.Empty;
        string firstPart = dn.Substring(dn.IndexOf("DC="));
        string secondPart = "CN=Partitions,CN=Configuration," + firstPart;
        DirectoryEntry root = new DirectoryEntry(secondPart, textBox2.Text, textBox3.Text);
        DirectorySearcher searcher = new DirectorySearcher(root);
        searcher.SearchScope = SearchScope.Subtree;
        searcher.ReferralChasing = ReferralChasingOption.All;
        searcher.Filter = "(&(nCName=" + firstPart + ")(nETBIOSName=*))";
        try
        {
            SearchResultCollection rs = searcher.FindAll();
            if (rs != null)
            {
                domain = GetProperty(rs[0], "nETBIOSName");
            }
        }
        catch (Exception ex)
        {

        }


        return domain;
22
ghost_mv

Dieser Artikel hat mir sehr geholfen zu verstehen, wie man mit Active Directory arbeitet.
Howto: (Almost) Everything In Active Directory via C#

Wenn Sie weitere Unterstützung benötigen, teilen Sie mir dies bitte mit entsprechenden Fragen mit, und ich werde sie nach bestem Wissen für Sie beantworten.

EDIT # 1

Du solltest lieber mit dem Filter dieses Beispiels gehen. Ich habe Beispielcode geschrieben, um kurz zu zeigen, wie mit den Namespaces System.DirectoryServices und System.DirectoryServices.ActiveDirectory gearbeitet wird. Der Namespace System.DirectoryServices.ActiveDirectory wird zum Abrufen von Informationen zu den Domänen in Ihrer Gesamtstruktur verwendet.

private IEnumerable<DirectoryEntry> GetDomains() {
    ICollection<string> domains = new List<string>();

    // Querying the current Forest for the domains within.
    foreach(Domain d in Forest.GetCurrentForest().Domains)
        domains.Add(d.Name);

    return domains;
}

private string GetDomainFullName(string friendlyName) {
    DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, friendlyName);
    Domain domain = Domain.GetDomain(context);
    return domain.Name;
}

private IEnumerable<string> GetUserDomain(string userName) {
    foreach(string d in GetDomains()) 
        // From the domains obtained from the Forest, we search the domain subtree for the given userName.
        using (DirectoryEntry domain = new DirectoryEntry(GetDomainFullName(d))) {
            using (DirectorySearcher searcher = new DirectorySearcher()){
                searcher.SearchRoot = domain;
                searcher.SearchScope = SearchScope.Subtree;
                searcher.PropertiesToLoad.Add("sAMAccountName");
                // The Filter is very important, so is its query string. The 'objectClass' parameter is mandatory.
                // Once we specified the 'objectClass', we want to look for the user whose login
                // login is userName.
                searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", userName);

                try {
                    SearchResultCollection  results = searcher.FindAll();

                    // If the user cannot be found, then let's check next domain.
                    if (results == null || results.Count = 0)
                        continue;

                     // Here, we yield return for we want all of the domain which this userName is authenticated.
                     yield return domain.Path;
                } finally {
                    searcher.Dispose();
                    domain.Dispose();
                }
            }
}

Hier habe ich diesen Code nicht getestet und möglicherweise ein kleineres Problem behoben. Dieses Beispiel wird in der vorliegenden Form zur Verfügung gestellt, um Ihnen zu helfen. Ich hoffe das wird helfen.

EDIT # 2

Ich habe einen anderen Ausweg gefunden:

  1. Sie müssen zunächst prüfen, ob Sie das Benutzerkonto in Ihrer Domäne finden können.
  2. Wenn gefunden, rufen Sie den NetBIOS-Namen der Domäne ab. und
  3. verketten Sie es zu einem Backslash (****) und dem gefundenen Login.

Das folgende Beispiel verwendet ein NUnit TestCase, das Sie selbst testen können und sehen, ob es das tut, was Sie benötigen.

[TestCase("LDAP://fully.qualified.domain.name", "TestUser1")] 
public void GetNetBiosName(string ldapUrl, string login)
    string netBiosName = null;
    string foundLogin = null;

    using (DirectoryEntry root = new DirectoryEntry(ldapUrl))
        Using (DirectorySearcher searcher = new DirectorySearcher(root) {
            searcher.SearchScope = SearchScope.Subtree;
            searcher.PropertiesToLoad.Add("sAMAccountName");
            searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login);

            SearchResult result = null;

            try {
                result = searcher.FindOne();

                if (result == null) 
                    if (string.Equals(login, result.GetDirectoryEntry().Properties("sAMAccountName").Value)) 
                        foundLogin = result.GetDirectoryEntry().Properties("sAMAccountName").Value
            } finally {
                searcher.Dispose();
                root.Dispose();
                if (result != null) result = null;
            }
        }

    if (!string.IsNullOrEmpty(foundLogin)) 
        using (DirectoryEntry root = new DirectoryEntry(ldapUrl.Insert(7, "CN=Partitions,CN=Configuration,DC=").Replace(".", ",DC=")) 
            Using DirectorySearcher searcher = new DirectorySearcher(root)
                searcher.Filter = "nETBIOSName=*";
                searcher.PropertiesToLoad.Add("cn");

                SearchResultCollection results = null;

                try {
                    results = searcher.FindAll();

                    if (results != null && results.Count > 0 && results[0] != null) {
                        ResultPropertyValueCollection values = results[0].Properties("cn");
                        netBiosName = rpvc[0].ToString();
                } finally {
                    searcher.Dispose();
                    root.Dispose();

                    if (results != null) {
                        results.Dispose();
                        results = null;
                    }
                }
            }

    Assert.AreEqual("FULLY\TESTUSER1", string.Concat(netBiosName, "\", foundLogin).ToUpperInvariant())
}

Die Quelle, aus der ich mich selbst inspiriert habe, ist:
Finden Sie den NetBios-Namen einer Domäne in AD

27

Da ich keinen Beispielcode finden konnte, möchte ich meine eigene Lösung mitteilen. Dadurch werden die übergeordneten Objekte des DirectoryEntry-Objekts durchsucht, bis es auf die domainDNS-Klasse trifft.

using System.DirectoryServices;

public static class Methods
{
    public static T ldap_get_value<T>(PropertyValueCollection property)
    {
        object value = null;
        foreach (object tmpValue in property) value = tmpValue;
        return (T)value;
    }

    public static string ldap_get_domainname(DirectoryEntry entry)
    {
        if (entry == null || entry.Parent == null) return null;
        using (DirectoryEntry parent = entry.Parent)
        {
            if (ldap_get_value<string>(parent.Properties["objectClass"]) == "domainDNS") 
                return ldap_get_value<string>(parent.Properties["dc"]);
            else 
                return ldap_get_domainname(parent);
        }
    }
}

Verwenden Sie es so:

string[] _properties = new string[] { "objectClass", "distinguishedName", "samAccountName", "userPrincipalName", "displayName", "mail", "title", "company", "thumbnailPhoto", "useraccountcontrol" };
string account = "my-user-name";
// OR even better:
// string account = "[email protected]";

using (DirectoryEntry ldap = new DirectoryEntry())
{
    using (DirectorySearcher searcher = new DirectorySearcher(ldap))
    {
        searcher.PropertiesToLoad.AddRange(_properties);
        if (account.Contains('@')) searcher.Filter = "(userPrincipalName=" + account + ")";
        else searcher.Filter = "(samAccountName=" + account + ")";
        var user = searcher.FindOne().GetDirectoryEntry();

        Console.WriteLine("Name: " + Methods.ldap_get_value<string>(user.Properties["displayName"]));
        Console.WriteLine("Domain: " + Methods.ldap_get_domainname(user));
        Console.WriteLine("Login: " + Methods.ldap_get_domainname(user) + "\\" + Methods.ldap_get_value<string>(user.Properties["samAccountName"]));
    }
}

Ich habe keinen Wald, um es zu testen, aber theoretisch sollte es ihn abschneiden.

5
Tiele Declercq

Sie können den Namen der Domäne abrufen, in der sich der aktuelle Benutzer befindet, und zwar mit der Environment.UserDomainName-Eigenschaft .

string domainName;
domainName = System.Environment.UserDomainName;
3
Mark

Vielleicht nicht ganz richtig, aber ...

DirectoryEntry dirEntry = new DirectoryEntry();         
DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry);
dirSearcher.SearchScope = SearchScope.Subtree;
dirSearcher.Filter = string.Format("(&(objectClass=user)(|(cn={0})(sn={0}*)(givenName={0})(sAMAccountName={0}*)))", userName);
var searchResults = dirSearcher.FindAll();

foreach (SearchResult sr in searchResults)
{
     var de = sr.GetDirectoryEntry();
     string user = de.Properties["SAMAccountName"][0].ToString();               
     string domain = de.Path.ToString().Split(new [] { ",DC=" },StringSplitOptions.None)[1];
     MessageBox.Show(domain + "/" + user);
}

Weil der Wert von de.Path ist

LDAP: // CN = FullName , DC = Domäne , DC = lokal

1
DartAlex