Как запросить как samaaccountname, так и userprincipalname symfonyLdap

У меня есть форма входа в Symfony, аутентифицирующая сервер Ldap. Я могу успешно запросить и аутентифицировать пользователя, используя имя samaccountname или userprincipalname и ключ uid в настройках моей конфигурации. Я хочу, чтобы пользователь мог вводить либо свое имя пользователя, либо имя пользователя@domain.com.

Я пробовал preg_replace для имени пользователя в методе loadUserbyUsername() в LdapUserProviderClass (я знаю, что это не идеально). Это берет имя пользователя, такое как [email protected], и передает имя пользователя. Мне удалось убедиться, что с сервера Ldap был возвращен правильный пользователь, но я все еще возвращаюсь к форме входа с «Недействительными учетными данными». Я считаю, что причина, по которой это происходит в запросе класса AuthenticationUtils, обрабатывается, а имя пользователя в запросе по-прежнему [email protected], и это не соответствует имени пользователя в пользовательском объекте, полученном из аутентификации Ldap, которая является именем пользователя. Если у кого-нибудь есть совет о том, как разрешить аутентификацию как [email protected], так и имени пользователя в Ldap, я был бы очень признателен.

SecurityController.php

 public function login(Request $request, AuthenticationUtils $authenticationUtils): Response
{


    // get the login error if there is one
    $error = $authenticationUtils->getLastAuthenticationError();
    // last username entered by the user
    $lastUsername = $authenticationUtils->getLastUsername();

    $newLastUsername = trim(preg_replace('/@.*/', '',$lastUsername));

    return $this->render('security/login.html.twig', ['last_username' => $newLastUsername, 'error' => $error]);
}

безопасность.yml

 providers:
        dsg_ldap:
        ldap:
            service: Symfony\Component\Ldap\Ldap
            base_dn: '%env(BASE_DSN)%'
            search_dn: '%env(SEARCH_DN)%'
            search_password: '%env(SEARCH_PWD)%'
            uid_key: '%env(UID_KEY)%'
            #filter: '({uid_key} = {_username})'
            default_roles: ROLE_USER
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        anonymous: ~

        form_login_ldap:
            login_path: login
            check_path: login
            service: Symfony\Component\Ldap\Ldap
            provider: dsg_ldap
            dn_string: '%env(DN_STRING)%\{username}'

Мой LdapUserProvider.php

    class LdapUserProvider extends SymfonyLdapUserProvider
{
    /** @var array maps ldap groups to roles */
    private $groupMapping = [
        '**' => '**',
        '**' => '**',
        '**' => '**',
        '**' => '**'

    ];

    /** @var string extracts group name from dn string */
      private $groupNameRegExp = '/CN=(.+?),/';

    protected function loadUser($username, Entry $entry)
    {
        $roles = ['ROLE_USER'];
        // Check if the entry has attribute with the group
        if (!$entry->hasAttribute('memberOf')) {
            return new User($username, '', $roles);
        }

        // Iterate through each group entry line
        foreach ($entry->getAttribute('memberOf') as $groupLine) {
            // Extract the group name from the line
            $groupName = $this->getGroupName($groupLine);
            // Check if the group is in the mapping
            if (array_key_exists($groupName, $this->groupMapping)) {
                // Map the group to the role(s) the user will have
                $roles[] = $this->groupMapping[$groupName];
            }
        }


        // Create and return the user object
        return new User($username, null, $roles);
    }

    /**
     * Get the group name from the DN
     * @param string $dn
     * @return string
     */
    private function getGroupName($dn)
    {
        $matches = [];
        return preg_match($this->groupNameRegExp, $dn, $matches) ? $matches[1] : '';
    }
}

Symfony\Component\Security\Core\User\LdapUserProvider.php

 public function loadUserByUsername($username)
{

    try {
        $this->ldap->bind($this->searchDn, $this->searchPassword);
        // what i added
        $username = trim(preg_replace('/@.*/', '',$username));
        $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
        $query = str_replace('{username}', $username, $this->defaultSearch);
        $search = $this->ldap->query($this->baseDn, $query);
    } catch (ConnectionException $e) {
        throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e);
    }

    $entries = $search->execute();
    $count = \count($entries);

    if (!$count) {
        throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
    }

    if ($count > 1) {
        throw new UsernameNotFoundException('More than one user found');
    }

    $entry = $entries[0];

    try {
        if (null !== $this->uidKey) {
            $username = $this->getAttributeValue($entry, $this->uidKey);
        }
    } catch (InvalidArgumentException $e) {
    }

    return $this->loadUser($username, $entry);
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
0
668
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В функции loadUserByUsername добавьте еще один запрос, если первый не удался. Ваш $this->defaultSearch, вероятно, является константой, представляющей фильтр LDAP.

Если вы создадите ту же строку в первом if (!$count) {...} вот так:

$query = str_replace('{username}', $username, "(userPrincipalName = {username})");

а затем выполните этот запрос, вы выполняете второй поиск userPrincipalName, который имеет форму пользователь@домен

Спасибо! Я смог заставить его работать, добавив ваши предложения. Кроме того, мне пришлось изменить dn_string: '%env(DN_STRING)%\{username}' на dn_string: ' '.

Brent 17.07.2019 16:46

Спасибо, что дал мне знать. Если ответ правильный, вы можете отметить его как таковой ;-)

mvreijn 18.07.2019 17:22

Другие вопросы по теме