一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

TP5.1 项目接入 LDAP 实现统一身份认证登录 企业级

时间:2026-07-10 10:11:46 编辑:袖梨 来源:一聚教程网

LDAP认证需先启用PHP ldap扩展并重启Web服务,再配置TP5.1的LDAP连接参数(如host、port=636、use_ssl=true、base_dn等),最后编写LdapAuth类实现DN查找、绑定验证与属性提取三阶段流程。

TP5.1项目需对接企业LDAP目录服务,让员工用域账号(如aduser或[email protected])直接登录后台系统,避免维护独立密码库。这要求ThinkPHP 5.1应用能完成LDAP连接、用户DN自动发现、凭据绑定验证、属性映射及会话初始化——任何一环缺失都会导致“用户名正确但登录失败”或“登录成功却拿不到姓名/部门等字段”。

安装并启用 PHP LDAP 扩展

TP5.1依赖PHP原生ldap扩展进行底层通信,未启用时调用ldap_connect()会直接报错Fatal error。确认扩展已加载是后续所有操作的前提。

执行php -m | grep ldap,若无输出则需启用:Ubuntu/Debian系统运行sudo phpenmod -v 7.4 ldap(版本号按实际PHP版本调整);CentOS/RHEL执行sudo yum install -y php-ldap后重启php-fpm或Apache。

【必须重启Web服务】否则即使扩展已安装,PHP进程仍无法识别ldap_*函数。

配置 LDAP 连接参数与认证方式

ThinkPHP本身不内置LDAP支持,需在application/config.php中新增配置段,明确区分开发与生产环境的服务器地址、端口、加密策略和基础搜索路径。

在return [ ... ]数组末尾追加:

'ldap' => [
  'host' => 'ldap.company.com',
  'port' => 636,
  'use_ssl' => true,
  'base_dn' => 'dc=company,dc=com',
  'admin_dn' => 'cn=ldap-reader,ou=service,dc=company,dc=com',
  'admin_password' => 'R3@dOnly2026!',
  'user_field' => 'sAMAccountName', // AD用此字段匹配登录名
  'mail_field' => 'mail',
  'name_field' => 'displayName'
],

注意:【port=636且use_ssl=true时,绝不可设为port=389】,否则TLS握手失败导致连接中断;AD环境务必用sAMAccountName而非uid,否则查不到用户。

编写 LDAP 认证服务类

将认证逻辑封装为独立服务类,便于复用和单元测试。该类需处理匿名搜索获取用户DN、二次绑定验证、属性提取三阶段流程。

在application/common/service/下新建LdapAuth.php:

第一步:定义构造函数,读取配置并初始化连接句柄

第二步:实现authenticate($username, $password)方法——先用admin账号连接LDAP,执行ldap_search()查找匹配$username的条目,提取其distinguishedName;再用该DN和$password调用ldap_bind()尝试绑定。

第三步:绑定成功后,立即调用ldap_get_entries()获取mail、displayName等字段,组装为关联数组返回;失败则返回false。

关键点:搜索过滤器必须写成"(&(objectClass=user)(sAMAccountName={$username}))"(AD)或"(uid={$username})"(OpenLDAP),括号缺一不可,否则返回空结果。

改造登录控制器调用 LDAP 服务

原有application/index/controller/Login.php中的login()方法需剥离本地数据库校验逻辑,改由LDAP服务接管。

方法一:直接实例化调用

$auth = new appcommonserviceLdapAuth();
$user = $auth->authenticate(input('post.username'), input('post.password'));

方法二:通过容器注入(推荐)

在application/common/service/LdapAuth.php顶部添加class LdapAuth implements thinkContainerInterface,并在Login控制器的__construct()中声明protected $ldapAuth;,框架自动注入实例。

若$user为数组,则调用session('user', $user)写入会话,并跳转至首页;若为false,返回统一错误提示“用户名或密码错误”。

映射 LDAP 属性到系统权限模型

LDAP只提供身份信息,TP5.1的RBAC权限控制仍需本地角色绑定。不能跳过这一步,否则用户虽能登录,但看不到任何菜单或按钮。

第一步:在用户首次LDAP登录成功后,检查think_user表中是否存在account字段等于$user['sAMAccountName']的记录。

第二步:若不存在,执行INSERT语句插入新用户,account设为LDAP登录名,nickname设为$user['displayName'],email设为$user['mail'],status默认为1。

第三步:调用Db::name('auth_group_access')->insert(['uid'=>$newId, 'group_id'=>5])将其加入预设的“普通员工”权限组(group_id=5需按实际ID调整)。

注意:【account字段必须唯一且非空】,否则重复插入会触发主键冲突,导致后续登录失败。

热门栏目