2017-08-30 1 views
0

Je construis ma première connexion API avec Symfony3 mais j'ai trébuché sur l'écouteur de connexion. Je souhaite qu'un événement soit déclenché dès que l'utilisateur s'est connecté avec succès aux diverses tâches habituelles, comme écrire un journal, générer un jeton, etc. Étant donné que les choses se passent par API, le système de connexion est un peu différent du formulaire de connexion classique décrit dans les guides Symfony. Dans cette optique, je suis sûr qu'il y a quelque chose qui me manque.L'écouteur de Symfony 3 ne fonctionne pas après la connexion

initialisation Listener:

// config/services.yml 
//... 

    login_listener: 
     class: 'User\LoginBundle\Listener\LoginListener' 
     tags: 
      - { name: 'kernel.event_listener', event: 'security.interactive_login', method: onSecurityInteractiveLogin } 

Mon Listener:

// User/LoginBundle/Listener/LoginListener.php 

namespace User\LoginBundle\Listener; 
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; 

class LoginListener 
{ 
    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
    { 
     echo 'Hello, I am the login listener!!'; 
    } 
} 

ma classe contrôleur

// User/LoginBundle/Controller/LoginController.php 
//... 

    public function checkCredentialsAction(Request $request) 
    { 
     $recursiveValidator = $this->get('validator'); 

     $user = new User; 
     $user->setUsername($request->request->get('username')); 
     $user->setPassword($request->request->get('password')); 


     $errors = $recursiveValidator->validate($user); 

     if (count($errors) > 0) { 
      $errorsString = (string) $errors; 

      return new JsonResponse($errorsString); 
     } 

     $loginService = $this->get('webserviceUserProvider.service'); 

     $user = $loginService->loadUserByUsernameAndPassword(
      $request->get('username'), 
      $request->get('password') 
     ); 

     if ($user instanceof WebserviceUser) { 
      return new JsonResponse('all right'); 

     } 

     return new JsonResponse('Username/password is not valid', 403); 
    } 

Mon composant de sécurité

security: 

    # https://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded 
    providers: 
     in_memory: 
      memory: ~ 

     api_key_user_provider: 
      id: AppBundle\Security\ApiKeyUserProvider 
#    property: apiKey 

     user_db_provider: 
      entity: 
       class: UserUserBundle:User 
#    property: username 

     webservice: 
      id: User\UserBundle\Security\User\WebserviceUserProvider 

    encoders: 
     User\UserBundle\Entity\User: 
      algorithm: bcrypt 

    firewalls: 
     # disables authentication for assets and the profiler, adapt it according to your needs 
     dev: 
      pattern: ^/(_(profiler|wdt)|css|images|js)/ 
      security: false 

     user_logged: 
      pattern: ^/logged 
      stateless: true 
      simple_preauth: 
       authenticator: AppBundle\Security\ApiKeyAuthenticator 
      provider: api_key_user_provider 

     main: 
      anonymous: ~ 
      form_login: 
       check_path: login/check 


    access_control: 
     - { path: ^/login/check, roles: IS_AUTHENTICATED_ANONYMOUSLY } 

Comme vous pouvez le voir la validation est effectuée contre l'entité et lorsque l'utilisateur/mot de passe est valide, le json retourné est return new JsonResponse('all right, you are logged in');. La validation est effectuée dans une classe Custom User Provider instanciée en service (méthode loadUserByUsernameAndPassword, ce qui est assez similaire à this),

Pourquoi l'utilisateur et le mot de passe sont valides et que la connexion se produit, l'auditeur n'est pas pris en compte comme un événement valide pour faire feu l'événement interactive_login?

+0

Apparaît que ce projet n'utilise pas le composant de sécurité :) –

+0

Je ne vois pas où vous vous connectez réellement à l'utilisateur. Où, par exemple, le stockage de jetons est-il mis à jour? – Cerad

+0

@MaxP. Je viens de mettre à jour mon post avec security.yml. –

Répondre

2

Si pour une raison quelconque, vous avez vraiment besoin de vous connecter manuellement un utilisateur puis ajoutez cette méthode à votre contrôleur et appel au moment opportun: dans la plupart des cas

private function loginUser(Request $request, UserInterface $user) 
{ 
    $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); 
    $this->get("security.token_storage")->setToken($token); 

    $event = new InteractiveLoginEvent($request, $token); 
    $this->get("event_dispatcher")->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $event); 
} 

if ($user instanceof WebserviceUser) { 
    $this->loginUser($request,$user); 
    return new JsonResponse('all right'); 
} 

Cependant, le système d'authentification existant (ou un authentificateur de garde personnalisé, https://symfony.com/doc/current/security/guard_authentication.html) le fera pour vous.

+0

Merci beaucoup. Cela fonctionne bien. Cependant, je vais jeter un coup d'œil à Guard, j'ai choisi de cette façon parce qu'en un coup d'œil ce n'était pas si clair pour moi et il semblait un peu surpuissant. Juste une question à ce sujet, pourquoi la variable '$ token'est-elle retournant une chaîne vide? –

+0

Les informations de jeton sont stockées dans la session. C'est ce qui permet à l'application de se souvenir des personnes qui se sont connectées entre les demandes. Je n'ai aucune idée de ce que vous voulez dire en retournant une chaîne vide. – Cerad

+0

ouais assez juste. J'ai compris.À la fin je l'ai développé avec guardd. C'était plus facile que ce à quoi je m'attendais. Heureusement ce post m'a beaucoup aidé https://stackoverflow.com/questions/34250444/symfony-2-guard-component-and-a-normal-login-form –