C#Active Directory:获取用户的域名? [英] C# Active Directory: Get domain name of user?

查看:384
本文介绍了C#Active Directory:获取用户的域名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这种类型的问题已经被问过了,但其他方法现在却让我失望。

I know that this type of question has been asked before, but other methods are failing me right now.

正如我们的Windows服务轮询AD一样,给定一个LDAP(即LDAP://10.32.16.80)以及该AD服务器中要搜索的用户组列表。
它检索这些给定组中的所有用户,并递归地搜索这些组以获取更多组。
然后将每个用户添加到另一个应用程序的身份验证用户列表中。

As it stands our windows service polls AD, given an LDAP (i.e. LDAP://10.32.16.80) and a list of usergroups within that AD server to search for. It retrieves all users within those given groups, recursively searching those groups for more groups as well. Each user is then added to another applications authenticated users list.

应用程序的这部分运行成功。但是,我们需要使用每个用户的友好域名(即登录DOMAIN /用户名的一部分)

This part of the application is running successfully. However, we're in need of each user's friendly domain name (i.e. the part of their login DOMAIN/username)

所以如果有一个用户是TEST的一部分域名,名叫史蒂夫:TEST /史蒂夫是他的登录。
我可以在AD中找到史蒂夫,但是我也需要TEST与他的AD信息一起存储。

So if there is a user that is part of TEST domain, named Steve: TEST/steve is his login. I'm able to find steve in the AD, however I also need "TEST" to be stored along with his AD information.

再次,我可以通过使用目录搜索器和LDAP IP来找到steve,但是给出LDAP IP,我如何找到友好的域名?

Again, I can find 'steve' fine by using a directory searcher and the LDAP IP I'm given, but given the LDAP IP, how can I find the friendly domain name?

我尝试以下代码尝试访问'defaultNamingContext'时给出错误:

When I try the following code I'm given an error when attempting to access the 'defaultNamingContext':

System.Runtime.InteropServices.COMException(0x8007202A):验证机制是未知。

System.Runtime.InteropServices.COMException (0x8007202A): The authentication mechanism is unknown.

这是代码:

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

编辑

我添加了这个示例方法,以尝试一个建议,但我得到一个例外:未指定的错误,当我在搜索器上的FindAll()调用。
要传递的字符串是:CN = TEST USER,CN = Users,DC = tempe,DC = ktregression,DC = com

I added this sample method in order to attempt a suggestion but am getting an exception: "Unspecified error" when I hit the "FindAll()" call on the searcher. The string being passed in is: "CN=TEST USER,CN=Users,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;


推荐答案

这篇文章帮助我了解如何使用Active Directory。

Howto :(几乎)通过C#活动目录中的所有内容

This article helped me much to understand how to work with the Active Directory.
Howto: (Almost) Everything In Active Directory via C#

从这一点开始,如果您需要进一步的工作,请通过正确的问题通知我,我将尽可能地回答他们。

From this point forward, if you require further assitance, please let me know with proper questions in comment, and I shall answer them for you to the best of my knowledge.

编辑# 1

您最好用此示例的过滤器替代。我已经编写了一些示例代码,以简要说明如何使用 System.DirectoryServices System.DirectoryServices.ActiveDirectory 命名空间。 System.DirectoryServices.ActiveDirectory 命名空间用于检索Forest中有关域的信息。

You had better go with this example's filter instead. I have written some sample code to briefly show how to work with the System.DirectoryServices and System.DirectoryServices.ActiveDirectory namespaces. The System.DirectoryServices.ActiveDirectory namespace is used to retrieve information about the domains within your Forest.

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();
                }
            }
}

测试这个代码,可能有一些小问题需要解决。此样本是为了帮助您而提供的。我希望这将有所帮助。

Here, I didn't test this code and might have some minor issue to fix. This sample is provided as-is for the sake of helping you. I hope this will help.

编辑#2

出路:


  1. 您首先要查看您是否可以在域中找到用户帐户;

  2. 如果找到,则获取域名NetBIOS名称;和

  3. 将其连接到反斜杠(****)和找到的登录名。

下面的例子使用了一个可以自己测试的NUnit TestCase ,看看它是否符合你的要求。

The example below uses a NUnit TestCase which you can test for yourself and see if it does what you are required to.

[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())
}

我启发自己的来源是:

在AD中查找域名的NetBios名称

The source from which I inspired myself is:
Find the NetBios Name of a domain in AD

这篇关于C#Active Directory:获取用户的域名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆