使用LDAP和实体提供者的Symfony身份验证

时间:2019-12-25 22:41:09

标签: security ldap symfony4 authenticator

我正在一个小型的symfony网站上,我需要LDAP身份验证。此外,在用户首次登录时,我需要在数据库中保留一个用户实体,以便将该用户实体链接到其他用户。

我设法通过使用自定义保护身份验证使其工作,该身份验证检查LDAP服务器以验证凭据。它还使用LdapUserProvider从LDAP信息生成User对象。

class LdapCustomAuthenticator extends AbstractFormLoginAuthenticator
{
    use TargetPathTrait;

    private $entityManager;
    private $urlGenerator;
    private $csrfTokenManager;
    private $ldapUserProvider;
    private $ldap;

    public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserProviderInterface $ldapUserProvider, LdapInterface $ldap)
    {
        $this->entityManager = $entityManager;
        $this->urlGenerator = $urlGenerator;
        $this->csrfTokenManager = $csrfTokenManager;
        $this->ldapUserProvider = $ldapUserProvider;
        $this->ldap = $ldap;
    }

    public function supports(Request $request)
    {
        return 'app_login' === $request->attributes->get('_route')
            && $request->isMethod('POST');
    }

    public function getCredentials(Request $request)
    {
        $credentials = [
            'username' => $request->request->get('_username'),
            'password' => $request->request->get('_password'),
            'csrf_token' => $request->request->get('_csrf_token'),
        ];
        $request->getSession()->set(
            Security::LAST_USERNAME,
            $credentials['username']
        );

        return $credentials;
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $token = new CsrfToken('authenticate', $credentials['csrf_token']);
        if (!$this->csrfTokenManager->isTokenValid($token)) {
            throw new InvalidCsrfTokenException();
        }



        $ldapUser = $this->ldapUserProvider->loadUserByUsername($credentials['username']);

        $localDBUser = $this->entityManager->getRepository(User::class)->findByUserName($credentials['username']);

        if (! $localDBUser){
            $this->entityManager->persist($ldapUser);
            $this->entityManager->flush();
            return $ldapUser;
        }else{
            $localDBUser->setDn($ldapUser->getDn());
            return $localDBUser;
        }
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        $username = $credentials['username'];
        $password = $credentials['password'];

        if ('' === (string) $password) {
            throw new BadCredentialsException('The presented password must not be empty.');
        }

        try {
            $this->ldap->bind($user->getDn(), $password);
            return true;
        } catch (ConnectionException $e) {
            return false;
        }
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
            return new RedirectResponse($targetPath);
        }

        return new RedirectResponse($this->urlGenerator->generate('home'));
    }

    protected function getLoginUrl()
    {
        return $this->urlGenerator->generate('app_login');
    }
}

我也在自定义LdapUserProvider,但是我跳过了细节。 但是在我的security.yaml中,我仍然使用EntityUserProvider:

security:
    providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: username

我的问题是在getUser方法的这些行中:

        $ldapUser = $this->ldapUserProvider->loadUserByUsername($credentials['username']);

        $localDBUser = $this->entityManager->getRepository(User::class)->findByUserName($credentials['username']);

        if (! $localDBUser){
            $this->entityManager->persist($ldapUser);
            $this->entityManager->flush();
            return $ldapUser;
        }else{
            $localDBUser->setDn($ldapUser->getDn());
            return $localDBUser;
        }

该方法不应在数据库中保存任何内容。但是由于我需要在用户首次登录时保留该用户,因此我看不到该代码在其他地方。

您有什么建议清理它?

0 个答案:

没有答案