Active Directory:在没有大量搜索的情况下查找组中用户的详细信息

时间:2013-07-05 08:53:26

标签: c# active-directory ldap directoryservices

好的,使用活动目录,剩下的一个要求就是撤回给定组中的所有用户并获取他们的详细信息 - 名字,姓氏,用户名,电子邮件。

在阅读完本文后,我惊讶地发现似乎没有办法以有效的方式做到这一点。我已经找到了两种获得结果的方法,但两者都显得非常浪费。

首先是搜索群组成员,如下所示:

        DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + server, username, password);
        DirectorySearcher search = new DirectorySearcher(searchRoot);
        search.Filter = string.Format("(|(CN={0})(CN={1}))", "Group1", "Group2");

        search.PropertiesToLoad.Add("member");
        SearchResultCollection results = search.FindAll();

它会返回包含用户名和仅用户名的单个结果。您可以将其解析为一个单独的用户名数组,然后获取每个用户的详细信息,您必须再次按名称搜索AD。

另一种方法是这样做:

   DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + server, username, password);
    DirectorySearcher search = new DirectorySearcher(searchRoot);
    search.Filter = string.Format("(&(&(objectClass=user)(objectCategory=person))(memberOf=*))");

    search.PropertiesToLoad.Add("memberOf");
    search.PropertiesToLoad.Add("name");
    search.PropertiesToLoad.Add("mail");
    search.PropertiesToLoad.Add("displayName");

    SearchResultCollection mySearchResultColl = search.FindAll();

    foreach (SearchResult result in mySearchResultColl)
    {
        foreach (string prop in result.Properties["memberOf"])
        {
            if (prop.Contains("Group1") || prop.Contain("Group2"))
            {
               //add user to list
            }
        }
    }

这让我得到了我想要的东西,但涉及检索每个活动目录用户,然后遍历集合以找到匹配的用户。这在我的小测试目录上运行良好,但我不禁想到它会在拥有数千名用户的系统上运行得有多慢。

我知道你可以使用PrinicpalContext对象做我需要的东西,但最好的我能告诉它只有在代码运行在同一个域中时才有用,我无法保证。我需要能够跨域查询。

有更好的方法吗?或者我只是不得不吮吸性能问题?

2 个答案:

答案 0 :(得分:1)

如果您只需要查找直接成员,则可以使用属性范围查询(ASQ)。 这需要2003年的域/林功能级别(忘记域或林)。

DirectoryEntry groupEntry = new DirectoryEntry("LDAP://<server>/<group DN>", "user", "pwd");

DirectorySearcher searcher = new DirectorySearcher(groupEntry);
searcher.SearchScope = SearchScope.Base;
searcher.AttributeScopeQuery = "member";
searcher.Filter = "(&(objectCategory=person)(objectClass=user))";
searcher.PropertiesToLoad.Clear();
searcher.PropertiesToLoad.Add("name");
searcher.PropertiesToLoad.Add("mail");
searcher.PropertiesToLoad.Add("displayName");

foreach (SearchResult result in searcher.FindAll())
{
    Console.WriteLine(result.Path);
}

对于嵌套组成员,您可以使用LDAP_MATCHING_RULE_IN_CHAIN匹配规则。 这需要2008 R2的域/林功能级别(再次,忘记域或林)。

DirectoryEntry rootEntry = new DirectoryEntry("GC://<server>", "user", "pwd");

DirectorySearcher searcher = new DirectorySearcher(rootEntry);
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = "(&(objectCategory=person)(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=<group DN>))";
searcher.PropertiesToLoad.Clear();
searcher.PropertiesToLoad.Add("name");
searcher.PropertiesToLoad.Add("mail");
searcher.PropertiesToLoad.Add("displayName");

foreach (SearchResult result in searcher.FindAll())
{
    Console.WriteLine(result.Path);
}

<强>限制:

  • 两种方法都不处理主要组成员身份
  • ASQ不能跨域工作,如果找到来自其他域的成员,则会抛出异常。通常,您只能对全局组执行此操作。

答案 1 :(得分:0)

您可以利用ANR搜索其中一些属性有关详细信息,请参阅此文章 - 自2000年以来该功能一直存在:

http://support.microsoft.com/kb/243299

为了搜索不在默认集中的其他属性,您需要调整架构(可能不适合您的情况)。