欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

ad 属性组 全名 CN=AAA,OU=BBB,,DC=baidu,DC=com,DC=cn php ldap 获取 这个属性组里面的所有成员

我自己亲自做的:   OK  OOK   有大用 有大大用

<?php    
//根据 属组名 搜索里面的成员   $full_property_name 是 DN ,是 很长的字串符 比如 "CN=AAA,OU=BBB,,DC=baidu,DC=com,DC=cn"    
function _get_ad_info_from_ad_by_property_name($full_property_name, $ad_user_property = array('*'), $diqu = 'js')    
{    
    $ad_connect_infos = _my_get_ad_connect_infos();    
    $ad_user = $ad_connect_infos[$diqu]['ad_user']; //域用户名 包含域名    
    $ad_pwd = $ad_connect_infos[$diqu]['ad_pwd'];    
    $host = $ad_connect_infos[$diqu]['host'];    
    $port = $ad_connect_infos[$diqu]['port'];//一般都是389    

   
    $conn = ldap_connect($host, $port); //不要写成ldap_connect($host.':'.$port)的形式    
    if ($conn) {    
        //设置参数    
        ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3); //声明使用版本3    
        ldap_set_option($conn, LDAP_OPT_REFERRALS, 0); // Binding to ldap server    
        $bd = ldap_bind($conn, $ad_user, $ad_pwd);    
        $basedn = $ad_connect_infos[$diqu]['basedn'];    
        if ($_GET['q'] == 'query_ad_info_ext' && $diqu = 'js') {//这是一种范围更大的 basedn    
            $basedn = 'dc=luxshare,dc=com,dc=cn';    
        } else if ($_GET['q'] == 'checking_ad_pwd' && $diqu = 'js') {//检查密码的时候,也检查所有的 范围更大的 basedn 吧    
            $basedn = 'dc=baidu,dc=com,dc=cn';    
        }else{    
            $basedn = 'dc=baidu,dc=com,dc=cn';    
        }    

        $groupDn = $full_property_name;

       # 下面这一行,过滤器很重要    

        $filter = "(&(objectCategory=person)(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=$groupDn))";    
        $justthese = $ad_user_property; //选择要获取的用户属性    
        $pageSize = 5000;    
        $cookie = '';    
        $infos = array();    
        do {    
            ldap_control_paged_result($conn, $pageSize, true, $cookie);    
            $sr = ldap_search($conn, $basedn, $filter, $justthese);    
            $tmp_infos = ldap_get_entries($conn, $sr);    
            $infos = array_merge($infos, $tmp_infos);    
            ldap_control_paged_result_response($conn, $sr, $cookie);    
        } while ($cookie !== null && $cookie != '');    

   
        if ($bd) {    
            //drupal_set_message('LDAP 连接成功'); //相当于登录成功    
        } else {    
            $infos = false;    
            drupal_set_message('LDAP 连接失败', 'warning');    
        }    
    } else {    
        $infos = false;    
        drupal_set_message('无法连接到AD域服务器', 'error');    
    }    
    ldap_close($conn);    
    return $infos;    
}    





下面给你一个完整、可直接用的 PHP + LDAP 示例,用于从 AD 里读取指定“属性组 / 安全组”中的所有成员

你的组 DN 是:

CN=AAA,OU=BBB,DC=baidu,DC=com,DC=cn    




一、核心思路(AD 里是怎么存的)

Active Directory 中:

  • 组对象有属性:member

  • member 是一个 DN 列表,每一项都是一个用户 / 组的 DN

  • PHP 通过 ldap_search()ldap_read() 读取这个属性即可


二、PHP 获取组成员(基础版,常用)

1️⃣ 示例代码

<?php $ldapHost = "ldap://your-ad-server.luxshare.com.cn"; $ldapUser = "LUXSHARE\\ldapbinduser";   // 域账号 $ldapPass = "password"; $baseDn   = "DC=baidu,DC=com,DC=cn"; $groupDn = "CN=AAA,OU=BBB,DC=baidu,DC=com,DC=cn"; // 连接 $ldapConn = ldap_connect($ldapHost); ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldapConn, LDAP_OPT_REFERRALS, 0); // 绑定 if (!ldap_bind($ldapConn, $ldapUser, $ldapPass)) {    die("LDAP bind failed"); } // 只读取 group 对象本身 $filter = "(objectClass=group)"; $attrs  = ["member"]; $result = ldap_read($ldapConn, $groupDn, $filter, $attrs); $entries = ldap_get_entries($ldapConn, $result); $members = []; if ($entries["count"] > 0 && isset($entries[0]["member"])) {    for ($i = 0; $i < $entries[0]["member"]["count"]; $i++) {        $members[] = $entries[0]["member"][$i];    } } // 输出成员 DN print_r($members); ldap_unbind($ldapConn);    




2️⃣ 输出结果示例

Array (    [0] => CN=ZhangSan,OU=Users,DC=baidu,DC=com,DC=cn    [1] => CN=LiSi,OU=Users,DC=baidu,DC=com,DC=cn    [2] => CN=IT-Group,OU=Groups,DC=baidu,DC=com,DC=cn )    



⚠️ 注意:

  • member 里可能包含“用户 + 嵌套组”

  • 上面拿到的是 DN,不是工号/邮箱


三、把成员 DN 再解析成用户名 / 邮箱(实战必用)

示例:获取 sAMAccountNamemail

$userAttrs = ["sAMAccountName", "mail", "displayName"]; $userList = []; foreach ($members as $memberDn) {    $res = ldap_read($ldapConn, $memberDn, "(objectClass=*)", $userAttrs);    $info = ldap_get_entries($ldapConn, $res);    if ($info["count"] > 0) {        $userList[] = [            "account" => $info[0]["samaccountname"][0] ?? "",            "name"    => $info[0]["displayname"][0] ?? "",            "mail"    => $info[0]["mail"][0] ?? "",        ];    } } print_r($userList);    




四、如果组里有「嵌套组」(Exchange/AD 很常见)

方案 1(推荐):使用 AD 的 LDAP_MATCHING_RULE_IN_CHAIN          #OK 有大用

$filter = "(&(objectCategory=person)(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=$groupDn))"; $attrs = ["sAMAccountName", "mail", "displayName"]; $result = ldap_search($ldapConn, $baseDn, $filter, $attrs); $entries = ldap_get_entries($ldapConn, $result);    



✅ 这个能一次性展开所有嵌套组成员
❌ 只在 Active Directory 可用(OpenLDAP 不支持)


五、常见坑(你这种环境很可能会遇到)

❗ 1. 成员太多(>1500)

AD 会限制 member 返回数量:

  • 解决方案:

    • LDAP_MATCHING_RULE_IN_CHAIN

    • 或分页(ldap_control_paged_result


❗ 2. Exchange Group

Exchange 创建的组:

  • 本质仍然是 AD group

  • member 属性正常存在

  • 不影响 LDAP 读取 ✅


❗ 3. 权限不够

如果 member 读不到:

  • 确认 bind 用户:

    • 至少是 普通域用户

    • 不要用被限制的服务账号


六、你如果需要,我可以继续帮你:

  • ✅ 写成 函数版 / 类

  • 递归展开嵌套组

  • 只取启用账号

  • 按工号 / 邮箱导出

  • 处理 1500+ 成员分页

直接告诉我你现在的使用场景(登录校验 / 通讯录 / 权限控制 / 同步数据库)。


普通分类: