Symfony3 FosUser и FosAuthServer, вход в систему пользователя с LDAP на AuthenticationFailureHandler - PullRequest
0 голосов
/ 05 июля 2018

Я работаю в Symfony с FosUser и FosAuthServer. У меня есть фронт веб-сайт, который имеет доступ к API Oauth2. На переднем веб-сайте, если пользователь не вошел в систему, перенаправьте его на oauth serveur, а после того, как пользователь войдет в систему, перенаправьте его на веб-сайт шрифтов с помощью токена oauth2.

Это хорошо работает, но мне нужно это: если пользователь находится в базе данных (мой пользовательский провайдер), продолжайте его если пользователь не найден в базе данных, я ищу его в LDAP и авторизирую его вручную.

Для этого я использую AuthenticationFailureHandler, чтобы найти пользователя в LDAP. Найдя его, я создаю пользовательскую сущность и отправляю событие FOSUserEvents :: SECURITY_IMPLICIT_LOGIN, но я не знаю, кто может создать токен и перенаправить его на передний веб-сайт.

security.yml

security:
    encoders:
        AppBundle\Entity\User: sha512
        Symfony\Component\Security\Core\User\User: plaintext

    providers:
        api:
            id: fos_user.user_provider.username_email
        admin:
            memory:
                users:
                    admin:  { password: password}

    firewalls:
        doc:
            pattern:  ^/api/doc
            anonymous: true

        oauth_token:
            pattern:  ^/oauth/v2/token
            security: false

        oauth_authorize:
            pattern:  ^/oauth/v2/auth
            guard:
                authenticators:
                    - app.security.login_form_authenticator
            form_login:
                provider: api
                csrf_token_generator: security.csrf.token_manager
                login_path: fos_user_security_login
                check_path: fos_user_security_check
                failure_handler: app.authentification_failure_handler
            logout:
                path: fos_user_security_logout
                target: fos_user_security_login
            anonymous: true

        admin:
            pattern:  ^/admin
            http_basic:
                realm:    'Secured Area'
                provider: admin
            anonymous:  false

        api:
            pattern:  ^/api
            fos_oauth:  true
            stateless:  true
            anonymous:  false



access_control:
    - { path: ^/oauth/v2/auth, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
    - { path: ^/api/doc, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
    - { path: ^/admin, roles: [ IS_AUTHENTICATED_FULLY ] }
    - { path: ^/, roles: [ ROLE_USER ] }

Service.yml

 app.authentification_failure_handler:
    public: false
    class: AppBundle\Handler\AuthenticationFailureHandler
    arguments:
        - '@utilities.active_directory.ageo'
        - '@doctrine.orm.entity_manager'
        - '@fos_user.user_manager'
        - '@security.token_storage'
        - '@debug.event_dispatcher'
        - '@router'
        - '@http_kernel'
        - '@security.http_utils'

AuthentificationFaillureHandler.php

<?php

namespace AppBundle\Handler;


use AppBundle\Entity\Assure;
use AppBundle\Entity\BrokerStructur;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use FOS\OAuthServerBundle\Model\AuthCodeManager;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\HttpUtils;


class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
   // private $cafeteriaEntityManager;
    private $router;

    /**
     * @var \Ageo\UtilitiesBundle\ActiveDirectory\Ageo      Connection au LDAP Ageo
     */
    private $ldap;

    /**
     * @var $entityManagerSql           Manager des entitées de la base mysql
     */
    private $entityManagerSql;

    /**
     * @var UserManager                 Manager des utilisateurs (FosUserBundle)
     */
    private $userManager;

    /**
     * @var EventDispatcher
     */
    private $eventDispatcher;

    /**
     * @var TokenStorage
     */
    private $tokenStorage;


    public function __construct(\Ageo\UtilitiesBundle\ActiveDirectory\Ageo $ldap, EntityManager $entityManagerSql, UserManager $userManager,
                                TokenStorage $tokenStorage, \Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher  $eventDispatcher,
                                RouterInterface $router, HttpKernelInterface $httpKernel, HttpUtils $httpUtils)
    {
        $this->ldap = $ldap;
        $this->router = $router;
        $this->entityManagerSql = $entityManagerSql;
        $this->userManager = $userManager;
        $this->tokenStorage = $tokenStorage;
        $this->eventDispatcher = $eventDispatcher;
        parent::__construct($httpKernel, $httpUtils, array(), null);

    }

    /**
     * Si l'utilisateur n'est pas présent dans la base de données local, on le cherche dans l'Active directory pour le logguer
     * On vérifie ensuite s'il existe dans la base de donné local. S'il existe, on le charge et on le met à jour, sinon, on le crée.
     * @param Request $request
     * @param AuthenticationException $exception
     * @return RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $username = trim($request->request->get('_username'));
        $password = trim($request->request->get('_password'));

        /*
         * Manupulation to find the user in LDAP => $userAd
         */
        $loaclUser = $this->userManager->createUser();
        $loaclUser
            ->setEnabled(true)
            ->setUsername($username)
            ->setPlainPassword($password)
            ->setEmail($userAd->hasAttribute('mail') ? $userAd->getAttribute('mail')[0] : null )

        $this->userManager->updateUser($loaclUser);

        $this->eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($loaclUser, $request));

        //$this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($loaclUser, $request, $response));

        // I need to login my user on authServeur


        // I have test this, but it's not working
        if ($this->session->has('_security.oauth_authorize.target_path'))
        {
            parse_str(parse_url($this->session->get('_security.oauth_authorize.target_path'), PHP_URL_QUERY), $target_path);
            $url = $this->session->get('_security.oauth_authorize.target_path');

        }
        $response = new RedirectResponse($url);



        return $response;
    }

}

Кто-нибудь скажет, кто мне может сделать тот же процесс, что и login_check?

1 Ответ

0 голосов
/ 05 июля 2018

Я никогда не делал этого, но, похоже, это случай использования цепочки провайдера

security:
    providers:
        chain_provider:
            chain:
                providers: [api, admin, ldap_provider]
...