GLPI界面LDAP认证故障:无法使用AD账号登录及同步用户
可能的核心原因
- LDAP过滤器HTML转义错误:GLPI配置中使用
&代替&,导致查询过滤器失效,无法匹配任何用户 - PHP LDAP模块默认使用LDAPv2,与AD的LDAPv3协议不兼容
- 绑定账号对AD用户关键属性的读取权限不足
- GLPI实体范围限制或配置文件参数覆盖界面设置
分步排查与解决步骤
1. 修正LDAP过滤器转义问题
进入GLPI的LDAP配置界面,将过滤器从(&(objectClass=user)(objectCategory=person))修改为(&(objectClass=user)(objectCategory=person)),保存后重新尝试用户导入和登录。
注:
&是HTML转义字符,LDAP查询需要直接使用逻辑与符号&,转义后的字符会被当作普通字符串处理,导致过滤器无法匹配任何用户。
2. 强制设置LDAP协议版本为v3
编辑GLPI配置文件glpi/config/config.php,添加或修改以下参数:
$CFG_GLPI['ldap_protocol_version'] = 3;
保存后重启Apache服务:
systemctl restart apache2
AD默认使用LDAPv3,而PHP ldap模块可能默认启用v2,协议版本不兼容会导致查询异常。
3. 验证绑定账号的属性读取权限
在Debian服务器上执行以下命令,检查绑定账号能否读取AD用户的关键属性:
ldapsearch -x -H ldap://<DC_IP> -D "cn=glpi_bind,cn=users,dc=domain,dc=local" -W -b "dc=domain,dc=local" "(sAMAccountName=你的测试用户名)" userAccountControl sAMAccountName objectguid
如果命令能正常返回用户的userAccountControl、sAMAccountName、objectguid属性值,说明权限正常;如果返回空或报错,需要在AD控制台给glpi_bind账号添加读取用户属性的权限。
4. 查看GLPI调试日志定位错误
开启GLPI的调试模式(在配置-常规设置-日志中设置日志级别为“调试”),然后查看glpi/files/_log/目录下的日志文件,搜索LDAP相关条目,获取登录或同步时的具体错误信息,比如过滤器无效、属性缺失等。
5. 检查AD用户的启用状态
使用ldapsearch命令确认测试用户的userAccountControl属性值:
ldapsearch -x -H ldap://<DC_IP> -D "cn=glpi_bind,cn=users,dc=domain,dc=local" -W -b "dc=domain,dc=local" "(sAMAccountName=你的测试用户名)" userAccountControl
- 值为
512:用户正常启用 - 值为
514:用户被禁用,需在AD中启用该用户
6. 排查GLPI实体与配置文件限制
- 确认LDAP配置中的“实体”设置为根实体,避免实体范围限制导致无法导入用户
- 检查
glpi/config/config.php中是否存在自定义LDAP参数(如$CFG_GLPI['ldap_server']),确保其值与界面配置一致,避免参数覆盖
7. 手动模拟GLPI的LDAP验证流程
创建一个PHP脚本test_ldap.php,内容如下:
<?php $dc_ip = "<DC_IP>"; $bind_dn = "cn=glpi_bind,cn=users,dc=domain,dc=local"; $bind_pwd = "你的绑定账号密码"; $test_user = "你的测试用户名"; $test_pwd = "测试用户密码"; $base_dn = "dc=domain,dc=local"; $ldapconn = ldap_connect("ldap://$dc_ip") or die("无法连接LDAP服务器"); ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3); if ($ldapconn) { // 绑定服务账号 $ldapbind = ldap_bind($ldapconn, $bind_dn, $bind_pwd); if ($ldapbind) { echo "服务账号绑定成功\n"; // 搜索用户 $filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=$test_user))"; $result = ldap_search($ldapconn, $base_dn, $filter); $entries = ldap_get_entries($ldapconn, $result); echo "找到用户数量:" . $entries['count'] . "\n"; if ($entries['count'] > 0) { // 验证用户密码 $userdn = $entries[0]['dn']; $userbind = ldap_bind($ldapconn, $userdn, $test_pwd); if ($userbind) { echo "用户身份验证成功\n"; } else { echo "用户身份验证失败:" . ldap_error($ldapconn) . "\n"; } } } else { echo "服务账号绑定失败:" . ldap_error($ldapconn) . "\n"; } ldap_close($ldapconn); } ?>
替换脚本中的占位符后,在服务器上执行:
php test_ldap.php
根据输出结果判断是搜索用户失败还是身份验证失败,进一步定位问题。
内容的提问来源于stack exchange,提问作者Ayoub Mesaoudi

