Symfony 6.4多LDAP服务配置报错:服务未找到求助
解决Symfony 6.4双LDAP服务配置登录报错问题
问题重现
配置主备两个LDAP服务后,登录时抛出错误:
Cannot check credentials using the "Symfony\Component\Ldap\Ldap" ldap service, as such service is not found. Did you maybe forget to add the "ldap" service tag to this service?
单个LDAP服务配置可正常工作,且通过php bin/console debug:container | grep ldap能确认自定义LDAP服务已存在。
错误原因
- Firewall配置错误:
form_login_ldap中的service参数填了类名Symfony\Component\Ldap\Ldap,但存在多个LDAP实例时,Symfony无法通过类名定位到具体服务,必须指定自定义的服务ID(如main_ldap)。 - Services配置笔误:
main_ldap服务的参数引用了不存在的@ldap_adapter,实际应该是你定义的@main_ldap_adapter。
修复步骤
1. 修正Firewall的LDAP服务引用
修改security.yaml中login防火墙的form_login_ldap配置,将service值改为你的主LDAP服务ID:
security: ... firewalls: login: pattern: ^/api/login provider: ldap_main_provider form_login_ldap: login_path: api_login check_path: api_login username_parameter: login password_parameter: password service: main_ldap # 替换为自定义的主LDAP服务ID dn_string: '%env(LDAP_DN_STRING)%' success_handler: App\Security\Authentication\AuthenticationSuccessHandler failure_handler: App\Security\Authentication\AuthenticationFailureHandler ...
2. 修复Services中的适配器引用错误
修改services.yaml里的main_ldap服务参数,把错误的@ldap_adapter改成@main_ldap_adapter:
services: ... main_ldap: class: Symfony\Component\Ldap\Ldap arguments: ['@main_ldap_adapter'] # 修正为正确的适配器服务ID tags: ['ldap'] backup_ldap: class: Symfony\Component\Ldap\Ldap arguments: ['@backup_ldap_adapter'] tags: ['ldap'] ...
3. 可选:实现主备LDAP自动切换
如果需要主LDAP故障时自动切换到备LDAP,可封装一个自定义LDAP服务:
第一步:创建自定义LDAP类
// src/Ldap/FallbackLdap.php namespace App\Ldap; use Symfony\Component\Ldap\Exception\ConnectionException; use Symfony\Component\Ldap\LdapInterface; class FallbackLdap implements LdapInterface { private LdapInterface $mainLdap; private LdapInterface $backupLdap; public function __construct(LdapInterface $mainLdap, LdapInterface $backupLdap) { $this->mainLdap = $mainLdap; $this->backupLdap = $backupLdap; } public function connect(string $host = null, int $port = null): void { try { $this->mainLdap->connect($host, $port); } catch (ConnectionException $e) { $this->backupLdap->connect($host, $port); } } public function bind(string $dn = null, string $password = null): void { try { $this->mainLdap->bind($dn, $password); } catch (ConnectionException $e) { $this->backupLdap->bind($dn, $password); } } // 实现LdapInterface的其他方法,统一委托给可用的LDAP实例 public function query(string $dn, string $query, array $options = []): \Symfony\Component\Ldap\Query\QueryInterface { try { return $this->mainLdap->query($dn, $query, $options); } catch (ConnectionException $e) { return $this->backupLdap->query($dn, $query, $options); } } public function escape(string $value, string $ignore = '', int $flags = 0): string { try { return $this->mainLdap->escape($value, $ignore, $flags); } catch (ConnectionException $e) { return $this->backupLdap->escape($value, $ignore, $flags); } } }
第二步:注册自定义服务
在services.yaml中添加:
services: ... App\Ldap\FallbackLdap: arguments: ['@main_ldap', '@backup_ldap'] tags: ['ldap'] ...
第三步:更新Security配置
使用自定义服务替换原有的LDAP服务:
security: ... providers: ldap_fallback_provider: ldap: service: App\Ldap\FallbackLdap base_dn: '%env(LDAP_BASE_DN)%' search_dn: '%env(LDAP_SEARCH_DN)%' search_password: '%env(LDAP_SEARCH_PASSWORD)%' default_roles: ROLE_USER uid_key: uid firewalls: login: provider: ldap_fallback_provider form_login_ldap: service: App\Ldap\FallbackLdap # 其他配置保持不变 ...
内容的提问来源于stack exchange,提问作者phpdev
相关产品推荐
相关产品推荐

