首页 > 解决方案 > Symfony 5.3 LDAP 新身份验证始终不是有效凭据

问题描述

我正在尝试使用 Symfony 5.3 中的新身份验证器管理器的 json_login_ldap,它似乎无法解析用户密码,并且我总是收到“无效凭据”错误消息并且无法登录。

如果我用我的数据尝试命令行 ldapsearch 它工作正常。在 Symfony 中调试我可以看到 ldap 用户数据。所以它在身份验证上失败了。

我的 security.yaml 是

security:
enable_authenticator_manager: true
password_hashers:
    Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'

providers:
    my_ldap:
        ldap:
            service: Symfony\Component\Ldap\Ldap
            base_dn: '%env(resolve:BASE_DN)%'
            search_dn: '%env(resolve:SEARCH_DN)%'
            search_password: '%env(resolve:LDAP_PASSWORD)%'
            default_roles: ROLE_USER
            uid_key: sAMAccountName

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        provider: my_ldap
        stateless: true
        json_login_ldap:
            service: Symfony\Component\Ldap\Ldap
            check_path: api_login
            username_path: security.credentials.login
            password_path: security.credentials.password
            search_dn: '%env(resolve:SEARCH_DN)%'
            search_password: '%env(resolve:LDAP_PASSWORD)%'
            dn_string: '%env(resolve:BASE_DN)%'
            query_string: 'sAMAccountName={username}'

access_control:
    # - { path: ^/admin, roles: ROLE_ADMIN }
    # - { path: ^/profile, roles: ROLE_USER }

声明 security.yaml 中使用的变量的 .env:

BASE_DN=OU=foo,OU=bar,OU=baz,OU=qux,DC=my,DC=example,DC=com
SEARCH_DN=cn=searchuser,ou=foo,ou=bar,ou=baz,ou=qux,dc=my,dc=example,dc=com
LDAP_PASSWORD=ldap_reader_password

并在 services.yaml

services:
_defaults:
    autowire: true
    autoconfigure: true

Symfony\Component\Ldap\Ldap:
    arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
    tags:
        - ldap
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
    arguments:
        -   host: my-host  # changed
            port: 389
            options:
                protocol_version: 3
                referrals: false

我正在发送失眠的数据以更快地进行测试。我正在请求一个带有数据的 POST 到 http://localhost:8101/api/login:

{
    "security": {
        "credentials": {
            "login": "test.username", 
            "password": "my_password"
        }
    }
}

我按照 symfony/ldap/Security/LdapUserProvider.php 的代码和函数 $this->loadUser($identifier, $entry) 末尾的 loadUserByIdentifier 实际上返回了一个带有 ldap 用户数据的 LdapUser 对象。但密码为空,而不是提供的密码。因此,在达到这一点之前,密码可能在某处丢失。

在 symfony\ldap\Security\LdapAuthenticator.php 中,authenticate 函数返回 Passport 对象,该对象具有 PasswordCredentials 和明文正确的用户提供的密码和resolved: false.

我在文档中没有找到 json_login_ldap 示例,但是项目几乎是空的,我只是尝试配置 ldap 登录,配置看起来很基本。为什么不解析用户密码?为什么我无法登录?我做错了什么?

谢谢您的帮助

编辑: ldapsearch 命令行是

ldapsearch -x -b "dc=my,cn=example,cn=com" -H ldap://my.example.com -D "cn=searchuser,ou=foo,ou=bar,ou=baz,ou=qux,dc=my,dc=example,dc=com" -W

然后询问密码并使用 ldap 用户列表进行回答。

使用 ldapsearch 命令:

ldapsearch -x -b "dc=my,cn=example,cn=com" -H ldap://my.example.com -D "cn=searchuser,ou=foo,ou=bar,ou=baz,ou=qux,dc=my,dc=example,dc=com" -W "sAMAccountName=test.username"

我得到以下数据:

# Test.Username, foo, bar, baz, qux, my.example.com
dn: CN=Test.Username,OU=foo,OU=bar,OU=baz,OU=qux,DC=my,DC=example,DC=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: test.username
sn: Username
c: EN
l: Randomcity
title: Assistant - departament
description: 8183-01234 |  | EN | PT | Regular/Permanent
postalCode: 04035
physicalDeliveryOfficeName: Fake Street, Randomcity, 04035, EN
telephoneNumber: +34 (555) 123456
givenName: Test
distinguishedName: CN=Test Username,OU=foo,OU=bar,OU=baz,OU=qux,DC=my,DC=example,DC=com
instanceType: 4
whenCreated: 20230213120051.0Z
whenChanged: 20411115070912.0Z
displayName: Test Username
uSNCreated: 151386
memberOf: CN=pim,OU=pam,OU=pum - Groups,DC=my,DC=example,DC=com
uSNChanged: 330517879
co: bar
department: bar | departament
company: example bar U.C.
proxyAddresses: x500:/o=example/ou=Exchange Group (FYDF231234PDLT)/cn=Recipients/cn=Test.Username
streetAddress: Fake Street
employeeType: PT
name: Test Username
objectGUID:: mxAQq12Jjky/4ycKabEPS6==
userAccountControl: 512
badPwdCount: 0
codePage: 0
countryCode: 123
employeeID: EN00123
badPasswordTime: 123810906564118891
lastLogoff: 0
lastLogon: 123808333912908124
pwdLastSet: 123708200340431193
primaryGroupID: 123
objectSid:: AQUAAAAABCDEAAAxf4pEoe3zO6g0v/wO4kCAA==
accountExpires: 9123472012354775807
logonCount: 309
sAMAccountName: test.username
sAMAccountType: 123306368
sIDHistory:: AQUABCDEAAUVAAAAd4oemO2qe8MmF4j+ZRkBAA==
showInAddressBook: CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,CN=pim,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=my,DC=example,DC=com
showInAddressBook: CN=All Users,CN=All Address Lists,CN=Address Lists Container,CN=pim,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=my,DC=example,DC=com
legacyExchangeDN: /o=pim/ou=External (FYDIBOHF25SPDLT)/cn=Recipients/cn=3f3dc637018b7653b68936ba11ed003d
userPrincipalName: enTUl01@my.example.com
lockoutTime: 0
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=my,DC=example,DC=com
dSCorePropagationData: 20212345670447.0Z
lastLogonTimestamp: 132814364123188798
msDS-SupportedEncryptionTypes: 0
textEncodedORAddress: X400:C=GB;A= ;P=example;O=London;S=Username;G=Test;
mail: Test.Username@example.com
manager: CN=Another Username,OU=foo,OU=bar,OU=baz,OU=qux,DC=my,DC=example,DC=com
msExchOmaAdminWirelessEnable: 4
msExchVersion: 44220981232016
msExchRemoteRecipientType: 4
mailNickname: TestUsername
msExchWhenMailboxCreated: 20130219124128.0Z
msExchMDBRulesQuota: 64
targetAddress: SMTP:TestUsername@fooAccess.mail.onmicrosoft.com
msExchSafeSendersHash:: fz/qCi123Qt86iU8888lolB1c6ddddUdL4Q77W9876rHu34
extensionAttribute1: EN
extensionAttribute11: 2015-May-08 12:05 by Workday
msExchArchiveQuota: 52123800
protocolSettings:: UE9QM8Klol123fCp8KnwqfCp8KytdfCp8Knwqc=
protocolSettings: 1
extensionAttribute12: Employee-PT
msExchMailboxGuid:: IPEaXbO1+0KPwAtZctyhBg==
msExchArchiveWarnQuota: 47112320
msExchPoliciesExcluded: {26491cfc-9e50-4857-861b-0cb8df22b5d7}
extensionAttribute4: bar | Finance
msExchRecipientDisplayType: -2112383642
extensionAttribute5: 255.255.255.255
msExchUMDtmfMap: reversedPhone:1234567890+
msExchUMDtmfMap: emailAddress:1234567890
msExchUMDtmfMap: lastNameFirstName:1234567890
msExchUMDtmfMap: firstNameLastName:1234567890
msExchTextMessagingState: 354021235
msExchTextMessagingState: 16123851
extensionAttribute6: EN001
msExchALObjectVersion: 119
extensionAttribute7: Active
msExchUserAccountControl: 0
msExchUMEnabledFlags2: -1
msExchRecipientTypeDetails: 2147123648
msExchELCMailboxFlags: 2
msExchDisabledArchiveGUID:: R/hxhWWlol123j1bfjZLNg==

当我询问 ldap 数据时,他们告诉我 uid_key 是 sAMAccountName。我认为这可能是问题所在。

我尝试将 security.yaml ldap provider uid_key 更改为 mail ( uid_key: mail),将 json_login_ldap dn_string 更改为 username ( dn_string: {username}),然后尝试使用电子邮件 test.username@example.com 登录,但我看到了同样的错误。

标签: authenticationldapsymfony5

解决方案


首先,确保正确配置了 ldap 提供程序。根据您的 ldapsearch 示例,它应该是(已解析环境变量):

providers:
    my_ldap:
        ldap:
            service: Symfony\Component\Ldap\Ldap
            base_dn: 'dc=my,cn=example,cn=com'
            search_dn: 'cn=searchuser,ou=foo,ou=bar,ou=baz,ou=qux,dc=my,dc=example,dc=com'
            search_password: '<searchuser_password>'
            default_roles: ROLE_USER
            uid_key: sAMAccountName

然后,对于 json 登录配置要考虑的重要一点是,它在设置dn_string时用作用户基础 dn query_string(这一点都不明显)。

query_string
使用此选项时,query_string将在指定的 DN 中进行搜索,dn_string并且 DN 结果query_string将用于使用密码对用户进行身份验证。

此外,文档中的示例显示search_dn并且search_password都在登录配置中设置(再次)。

按照这两点,这应该有效:

json_login_ldap:
    service: Symfony\Component\Ldap\Ldap
    check_path: api_login
    username_path: security.credentials.login
    password_path: security.credentials.password
    search_dn: 'cn=searchuser,ou=foo,ou=bar,ou=baz,ou=qux,dc=my,dc=example,dc=com'
    search_password: '<searchuser_password>'
    dn_string: 'dc=my,cn=example,cn=com'
    query_string: 'sAMAccountName={username}'

推荐阅读