PHP中LDAP搜索过滤器无法排除指定OU的问题求助
解决PHP LDAP查询AD时排除特定OU用户的问题
你的核心问题在于错误使用了LDAP过滤器的字段:
- 用户对象的
ou属性并非用来记录其所在的组织单元,直接过滤(!(ou=USERS))完全无效。 memberOf仅适用于组(Group),OU不是组,用户不会成为OU的成员,所以用memberOf匹配OU也不成立。
下面是三种可行的解决方案:
方案一:通过distinguishedName在LDAP过滤器中排除用户
每个AD用户的distinguishedName(DN)包含了完整的路径信息(比如CN=张三,OU=USERS,DC=TOTO,DC=COM),我们可以通过匹配DN来排除指定OU下的所有用户。
修改后的过滤器代码:
// 先对搜索关键词做LDAP转义,防止注入 $nom = ldap_escape($_POST['nom'], '', LDAP_ESCAPE_FILTER); $base_dn = "DC=TOTO, DC=COM"; // 排除OU=USERS和OU=TEST下的所有用户(包括子OU) $filter = "(&(objectClass=person)(|(givenname=*$nom*)(sn=*$nom*))(!(distinguishedName=*,OU=USERS,DC=TOTO,DC=COM))(!(distinguishedName=*,OU=TEST,DC=TOTO,DC=COM)))"; $attributes = ["sn", "givenname", "mail"];
- 这里的
distinguishedName=*,OU=USERS,...会匹配所有DN结尾为该OU路径的用户,也就是整个OU树(含子OU)下的用户都会被排除。 - 一定要用
ldap_escape处理用户输入,避免LDAP注入风险。
方案二:在PHP代码中过滤结果
如果LDAP服务器不支持复杂过滤器,或者你需要更灵活的判断,可以在获取搜索结果后,通过代码跳过指定OU的用户:
foreach ($entries as $entry) { if (isset($entry['cn'][0])) { // 获取用户的完整DN $userDn = $entry['dn']; // 检查是否属于要排除的OU if (strpos($userDn, 'OU=USERS,DC=TOTO,DC=COM') !== false || strpos($userDn, 'OU=TEST,DC=TOTO,DC=COM') !== false) { continue; // 跳过该用户 } // 正常处理结果 $result = [ 'sn' => isset($entry['sn'][0]) ? $entry['sn'][0] : ' ', 'givenname' => isset($entry['givenname'][0]) ? $entry['givenname'][0] : ' ', 'mail' => isset($entry['mail'][0]) ? $entry['mail'][0] : 'Non renseigné', ]; array_push($results, $result); } }
方案三:拆分搜索范围(适用于OU结构简单的场景)
如果你的AD中用户分布在明确的几个OU,且排除的OU数量很少,可以直接针对需要包含的OU分别执行ldap_search,再合并结果。比如:
// 只搜索允许的OU $allowedOus = [ "OU=Allowed1,DC=TOTO,DC=COM", "OU=Allowed2,DC=TOTO,DC=COM" ]; $results = []; foreach ($allowedOus as $ou) { $search_result = ldap_search($ldap_conn, $ou, $filter, $attributes); $entries = ldap_get_entries($ldap_conn, $search_result); // 处理并合并结果... }
这种方式无需过滤,但如果OU结构复杂会比较繁琐。
内容的提问来源于stack exchange,提问作者Kryyys
相关产品推荐
相关产品推荐

