LDAP-在MemberOf过滤器上使用通配符

时间:2019-03-21 10:19:44

标签: c# active-directory ldap wildcard directorysearcher

我需要从特定类别中获取所有用户及其组。

用户示例:

user  | memberof
user1 | CN=group_1,OU=Groupes,OU=CR 1,DC=zcam,DC=ztech
user1 | CN=group_2,OU=Groupes,OU=CR 1,DC=zcam,DC=ztech
user2 | CN=group_2,OU=Groupes,OU=CR 1,DC=zcam,DC=ztech
user3 | CN=group_3,OU=Groupes,OU=CR 2,DC=zcam,DC=ztech

我需要获取memberof包含OU=Groupes,OU=CR 1,DC=zcam,DC=ztech的每个用户(本例中为user1和user2)

按照该文档(https://docs.microsoft.com/fr-fr/windows/desktop/ADSI/search-filter-syntax)我尝试了以下语法:

DirectoryEntry ldap = new DirectoryEntry("LDAP://xxx.xxx.xxx.xxx");
using (DirectorySearcher searcher = new DirectorySearcher(ldap))
{
    // Works but return everything
    searcher.Filter = "(&(objectClass=user)(memberof=*))";

    // Works but only for one group
    searcher.Filter = "(&(objectClass=user)(memberof=CN=group_1,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh))";

    // Doesn't work because searcher.FindAll().Count returns 0
    searcher.Filter = "(&(objectClass=user)(memberof=*,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh))";

    // searcher.FindAll().Count returns 0
    foreach (SearchResult result in searcher.FindAll()) 
    {
        [...]
    }

此(https://community.servicenow.com/community?id=community_question&sys_id=00d29fa1db101fc01dcaf3231f96197f之后,我尝试用*更改通配符%,但是并没有改变结果。

3 个答案:

答案 0 :(得分:1)

  

我需要让每个用户的memberof包含OU = Groupes,OU = CR 1,DC = zcam,DC = ztech(在我的示例中为user1和user2)

如果我理解正确,我认为这句话概括了您要尝试做的事情。您要查找该OU中任何组的成员的所有用户。

Active Directory不允许您在带有distinguishedName的任何属性上使用通配符。其中包括membermemberOf。因此,执行此操作的唯一方法是分两个步骤:

  1. 找到该OU中所有组的distinguishedName
  2. 搜索其memberOf包含步骤1中找到的值之一的所有用户。

这样的事情(我还没有针对AD进行过测试,因此您可能需要对其进行调整):

var groupSearch = new DirectorySearcher(
    new DirectoryEntry("LDAP://OU=Groupes,OU=CR 1,DC=zcam,DC=ztech"), //notice the OU
    "(objectClass=group)");

//if you don't do this, it will return *every* attribute, which is slower
groupSearch.PropertiesToLoad.Add("distinguishedName");

//build a user query with all the groups
var userFilter = new StringBuilder("(&(objectClass=user)(|");
using (var results = groupSearch.FindAll()) {
    foreach (SearchResult result in results) {
        userFilter.Append($"(memberOf={result.Properties["distinguishedName"][0]})");
    }
}
userFilter.Append(")");

var userSearch = new DirectorySearcher(
    new DirectoryEntry("LDAP://DC=zcam,DC=ztech"),
    userFilter.ToString());

//userSearch.PropertiesToLoad.Add(""); //add only the attributes you need to make it quicker

using (var results = userSearch.FindAll()) {
    foreach (SearchResult result in results) {
        //do something
    }
}

请注意,这只会找到这些组的 direct 个成员。它不会返回嵌套组中的用户(当用户属于这些组之一的组中)。如果需要的话,可以调整过滤器以包括一个特殊的标志,该标志告诉AD进行递归搜索:

userFilter.Append($"(memberOf:1.2.840.113556.1.4.1941:={result.Properties["distinguishedName"][0]})");

根据您的域,您可能需要了解两件事:

  1. 这不会返回将其中一个组作为主要组的用户,因为该关系不是使用member / memberOf存储的。
  2. 如果这些组具有来自外部受信任域的成员,那么最终您将找到“外部安全主体”对象,而不是其实际用户对象。如果这对您来说是另一回事,那就要处理了。

如果您很好奇,我已经写了几篇有关该主题的文章。从这个开始:Active Directory: What makes a member a member?

答案 1 :(得分:0)

编辑版本;扩展您所有的group_X

(
&(objectClass=user)
(|(memberof=CN=group_1,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh)
(memberof=CN=group_2,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh))
)

答案 2 :(得分:0)

最后,我找到了另一种方法。 实际上,OU=CR 1中的属性memberof对应于我的广告中的部门。 所以我只是这样过滤:

DirectoryEntry ldap = new DirectoryEntry("LDAP://xxx.xxx.xxx.xxx");
using (DirectorySearcher searcher = new DirectorySearcher(ldap))
{
    searcher.Filter = "(&(objectClass=user)(division=CR 1))";

    foreach (SearchResult result in searcher.FindAll()) 
    {
        [...]
    }

感谢大家的帮助。