PHP 5.6下通过LDAP操作Active Directory:搜索、更新及密码验证
解决PHP 5.6下Active Directory的密码验证与用户数据更新问题
一、密码验证:别纠结userPassword,用绑定验证才是正道
首先得给你明确个关键点:Active Directory 绝对不会返回用户的明文密码或可直接比对的哈希值,userPassword字段要么根本不对外暴露,要么存的是没法直接用的格式,所以你想靠搜索结果拿密码对比的路子走不通。正确的做法是用用户输入的凭证重新绑定LDAP连接——绑定成功就说明密码没问题。
具体步骤和代码示例:
- 先用一个有查询权限的服务账号(如果你的AD允许匿名查询,也可以不用)连接LDAP,先找到目标用户的完整DN(比如
CN=user_name,OU=Users,DC=shamsa,DC=real,DC=kamchatka,DC=ru); - 用这个用户的DN和用户输入的密码,调用
ldap_bind()尝试重新绑定; - 绑定成功=密码正确,失败就是密码错了。
$host = "你的AD服务器地址"; $port = 389; // 服务账号(用来查询用户DN,没有的话可以尝试匿名绑定) $serviceDn = "CN=ServiceAccount,OU=Services,DC=shamsa,DC=real,DC=kamchatka,DC=ru"; $servicePassword = "服务账号密码"; // 初始化连接并设置必要参数(LDAPv3必须开,否则容易出问题) $ldapConn = ldap_connect($host, $port); ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldapConn, LDAP_OPT_REFERRALS, 0); // 禁用引用,避免AD的一些奇怪问题 // 先用服务账号绑定 if (!ldap_bind($ldapConn, $serviceDn, $servicePassword)) { die("服务账号绑定失败: " . ldap_error($ldapConn)); } // 搜索目标用户,只获取DN字段就行 $searchBase = "DC=shamsa,DC=real,DC=kamchatka,DC=ru"; $filter = "(&(objectClass=user)(CN=user_name))"; $attributes = ["dn"]; $result = ldap_search($ldapConn, $searchBase, $filter, $attributes); $entries = ldap_get_entries($ldapConn, $result); if ($entries["count"] === 0) { die("没找到这个用户"); } $userDn = $entries[0]["dn"]; // 用用户输入的密码尝试绑定验证 $userInputPassword = "用户输入的密码"; $authSuccess = ldap_bind($ldapConn, $userDn, $userInputPassword); if ($authSuccess) { echo "密码验证通过!"; } else { echo "密码错误: " . ldap_error($ldapConn); } // 记得关闭连接 ldap_unbind($ldapConn);
二、搜索并更新AD用户数据
1. 灵活搜索用户(补充点实用技巧)
你已经会基础搜索了,这里给个批量搜索的例子,比如找所有没被禁用的用户,同时指定要获取的属性:
// 过滤条件:排除禁用账号(userAccountControl的2位代表禁用) $filter = "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"; $attributes = ["cn", "mail", "telephoneNumber"]; // 只拿需要的属性,减少返回数据量 $result = ldap_search($ldapConn, $searchBase, $filter, $attributes); $entries = ldap_get_entries($ldapConn, $result); // 遍历结果 for ($i = 0; $i < $entries["count"]; $i++) { echo "用户名: " . $entries[$i]["cn"][0] . "<br>"; echo "邮箱: " . $entries[$i]["mail"][0] . "<br>"; }
2. 更新用户数据
要更新AD用户,必须用有修改权限的账号(比如AD管理员账号)绑定LDAP,然后用ldap_mod_replace()(替换属性值)、ldap_mod_add()(添加属性值)或ldap_mod_del()(删除属性值)来操作。注意AD的属性名是固定的,比如邮箱是mail,电话是telephoneNumber。
代码示例:更新用户的邮箱和手机号
// 用有权限的管理员账号绑定 $adminDn = "CN=AdminUser,OU=Admins,DC=shamsa,DC=real,DC=kamchatka,DC=ru"; $adminPassword = "管理员密码"; ldap_bind($ldapConn, $adminDn, $adminPassword); // 目标用户的DN(可以通过搜索获取) $userDn = "CN=user_name,OU=Users,DC=shamsa,DC=real,DC=kamchatka,DC=ru"; // 要更新的属性数组,注意值是数组格式(哪怕是单值属性) $updateData = [ "mail" => ["new-user@example.com"], "telephoneNumber" => ["+71234567890"] ]; // 执行修改 $modifySuccess = ldap_mod_replace($ldapConn, $userDn, $updateData); if ($modifySuccess) { echo "用户数据更新成功!"; } else { echo "更新失败: " . ldap_error($ldapConn); }
小提示:如果是多值属性(比如用户的别名),可以给数组传多个值;如果只是想添加新值而不是替换,就用
ldap_mod_add(),删除值用ldap_mod_del()。
内容的提问来源于stack exchange,提问作者Yazu
相关产品推荐
相关产品推荐

