Аутентификация в symfony api с ldaptools + jwt + fosuser

В моем api я пытаюсь аутентифицировать пользователя с помощью LdapИнструментыBundle, FOSUserBundle и LexikJWTAuthenticationBundle. Выполняя действия шаг за шагом и следуя документация по интеграции для fosuser и ldaptools и более поздним документам jwt, мне удается выполнить следующее:

  1. FosUserBundle + LdapToolsBundle прошел успешно
  2. Интеграция API + FosUserBundle + LdapToolsBundle прошла успешно
  3. Ошибка Jwt + FosUserBundle + LdapToolsBundle на Api.

проблема в том, что я могу войти только в свою базу данных, но не в ldap.

в моей базе данных есть одна пользовательская запись, которую я создал с помощью команды fos и любого пароля (чтобы убедиться, что аутентификация выполняется на ldap, а не на fosuser). Все идет нормально. но после установки JWT аутентификация выполняется fosuser вместо защиты аутентификации ldap. Когда я меняю пароль с помощью команды fos, я могу получить токен без проблем.

это мой конфиг:

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt
        LdapTools\Bundle\LdapToolsBundle\Security\User\LdapUser: plaintext

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

        ldap:
            id: ldap_tools.security.user.ldap_user_provider

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        api_login:
            pattern:  ^/login
            stateless: true
            provider: fos_userbundle
            anonymous: true
            form_login:
                check_path:               /login
                require_previous_session: false
                username_parameter:       username
                password_parameter:       password
                success_handler:          lexik_jwt_authentication.handler.authentication_success
                failure_handler:          lexik_jwt_authentication.handler.authentication_failure
                require_previous_session: false
            guard:
                authenticators:
                    - ldap_tools.security.ldap_guard_authenticator
            logout: true

        api:
            pattern:   ^/
            stateless: true
            lexik_jwt: ~

    access_control:
        - { path: ^/login$,           role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/,                 role: IS_AUTHENTICATED_FULLY }

У меня вопрос, как мне заставить работать аутентификатор ldap? Я покажу нужный рабочий процесс

  1. Получен запрос аутентификации (имя пользователя и пароль)
  2. Провайдер fosuser находит пользователя или пользователя не найденными (неверные учетные данные -> конец)
  3. Защита аутентификатора ldap проверяет подлинность пользователя на сервере домена или неверных учетных данных -> конец
  4. Пользователь успешно вошел в систему, и токен получен

но я все еще получаю неверные учетные данные с зарегистрированным пользователем в базе данных и на сервере домена (учетные данные пользователя работают)

Заранее спасибо!

Стоит ли изучать 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
708
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Покопайтесь в аутентификаторе ldap_tools.security.ldap_guard_authenticator (namespace LdapTools\Bundle\LdapToolsBundle\Security;) Я нашел это

 public function getUser($credentials, UserProviderInterface $userProvider)
{
    $domain = $this->ldap->getDomainContext();

    try {
        $credDomain = isset($credentials['ldap_domain']) ? $credentials['ldap_domain'] : '';
        $this->switchDomainIfNeeded($credDomain);
        $this->setLdapCredentialsIfNeeded($credentials['username'], $credentials['password'], $userProvider);
        $user = $userProvider->loadUserByUsername($credentials['username']);
        $this->userChecker->checkPreAuth($user);

        return $user;
    } catch (UsernameNotFoundException $e) {
        $this->hideOrThrow($e, $this->options['hide_user_not_found_exceptions']);
    } catch (BadCredentialsException $e) {
        $this->hideOrThrow($e, $this->options['hide_user_not_found_exceptions']);
    } catch (LdapConnectionException $e) {
        $this->hideOrThrow($e, $this->options['hide_user_not_found_exceptions']);
    } catch (\Exception $e) {
        $this->hideOrThrow($e, $this->options['hide_user_not_found_exceptions']);
    } finally {
        $this->switchDomainBackIfNeeded($domain);
    }
}

Этот метод загружает пользователя с указанием пользователя и некоторых учетных данных.

Итак, getUser полагается на userprovider для загрузки любого пользователя, но поскольку вы используете fos_userbundle в качестве userprovider для вашего брандмауэра api_login, вы фактически аутентифицируетесь в своей локальной базе данных. Попробуйте вместо этого использовать в своей конфигурации ldap userprovider.

Конечно, при этом вы будете аутентифицироваться на сервере ldap, а не в потоке, который вы описали выше. Для этого рассмотрите возможность самостоятельной обработки аутентификации, чтобы вы могли обрабатывать поток по своему усмотрению. Также вы можете сделать это так пользовательский аутентификатор и в вашем public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) вы можете проверить учетные данные на вашем сервере ldap с помощью службы "@ldap_tools.ldap_manager"->authenticate($user, $password, &$errorMessage = false, &$errorNumber = false).

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

Вот мой ответ: просто принудительно авторизуйтесь после проверки сервера ldap.

public function onAuthenticationFailure(AuthenticationFailureEvent $event)//when auth fails on DB(Allways!!!)
    {
        $userToken = $event->getAuthenticationToken();
        $username = $userToken->getUsername();
        $password = $this->requestStack->getCurrentRequest()->get('password');

        if ($this->ldapManager->authenticate($username, $password)) {//good credentials
            $token = new UsernamePasswordToken($userToken, 'yes', "public", $userToken->getRoles());
            $this->container->get('security.token_storage')->setToken($token);//set a token

            $event = new InteractiveLoginEvent($this->requestStack->getCurrentRequest(), $token); //dispatch the auth event
            $event->stopPropagation();
            $this->container->get('event_dispatcher')->dispatch(SecurityEvents::INTERACTIVE_LOGIN,$event);

        }
        //symfony takes care of the response
        }

Пока это лучший ответ, который я нашел

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