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

查看:26
本文介绍了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 域的一部分,名为 Steve:TEST/steve 是他的登录名.我可以在 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 找到史蒂夫",但是给定 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# 在 Active Directory 中

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.DirectoryServicesSystem.DirectoryServices.ActiveDirectory 命名空间.System.DirectoryServices.ActiveDirectory 命名空间用于检索有关林中域的信息.

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("FULLYTESTUSER1", string.Concat(netBiosName, "", foundLogin).ToUpperInvariant())
}

我的灵感来源是:
在 AD 中查找域的 NetBios 名称

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

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