首页 文章

Symfony3 FosUser和FosAuthServer,在AuthenticationFailureHandler上使用LDAP登录用户

提问于
浏览
0

我正在使用FosUser和FosAuthServer进行symfony . 我有一个前端网站,可以访问Oauth2的API . 在前端网站上,如果用户未登录,则将其重定向到oauth服务器,并在用户登录后,使用oauth2令牌将其重定向到字体网站 .

它运行良好,但我需要这个:如果在数据库(我的用户提供商)中找到用户,如果在数据库中找不到用户,请在他中搜索,我在LDAP中搜索他并手动登录他 .

为此,我使用AuthenticationFailureHandler在LDAP中查找用户 . 找到他之后,我创建了一个用户实体并发送了envent 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 回答

  • 1

    我从来没有这样做但这似乎是chain provider的用例

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

相关问题