0

在我的 api 中,我尝试使用LdapToolsBundleFOSUserBundleLexikJWTAuthenticationBundle对用户进行身份验证。一步一步地做事,并遵循fosuser 和 ldaptools 的集成文档以及后来的 jwt 文档,我设法完成了以下操作:

  1. FosUserBundle + LdapToolsBundle 成功
  2. Api 集成 + FosUserBundle + LdapToolsBundle 成功
  3. Api 上的 Jwt + FosUserBundle + LdapToolsBundle 失败。

问题是我只能登录我的数据库,但不能登录 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. 用户登录成功,收到token

但我仍然在数据库和域服务器中获得注册用户的错误凭据(用户凭据有效)

提前致谢!

4

2 回答 2

0

深入研究 ldap_tools.security.ldap_guard_authenticator authenticationator( 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的是 api_login 防火墙的 userprovider,因此实际上您是在对本地数据库进行身份验证。尝试在您的配置中使用 ldap userprovider。

当然,这样做您将针对 ldap 服务器而不是您上面描述的流程进行身份验证。为此,请考虑自己处理身份验证,以便您可以根据需要处理流程。您也可以像这个 customauthenticator一样做,并且public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) 您可以使用该服务检查您的 ldap 服务器的凭据"@ldap_tools.ldap_manager"->authenticate($user, $password, &$errorMessage = false, &$errorNumber = false)

于 2018-04-25T19:22:10.823 回答
0

这是我的答案:在检查 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
        }

到目前为止,这是我找到的最佳答案

于 2018-04-27T19:47:25.773 回答