2017-08-30 69 views
0

我正在用Symfony3構建我的第一個API登錄,但是我在登錄偵聽器上絆倒了。我想在用戶成功登錄後立即啓動一個事件,以實現各種常用目的,例如編寫日誌,生成令牌等。 因爲事情正在通過API發生,所以登錄系統與在Symfony指南中描述的經典登錄表單。有鑑於此,我肯定有些事我錯過了。登錄後Symfony 3偵聽器無法運行

監聽器初始化:

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

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

我的聽衆:

// 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!!'; 
    } 
} 

我的控制器類

// 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); 
    } 

我的安全組件

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 } 

正如你所看到的驗證是針對實體進行的,並且當用戶/密碼有效時,返回的json是return new JsonResponse('all right, you are logged in');。驗證被實例化服務(方法loadUserByUsernameAndPassword,它是相當類似this)自定義用戶提供一流的完成,

爲什麼當用戶和密碼是否有效並出現登錄,聽者不考慮作爲一個有效的事件使interactive_login事件發生火災?

+0

似乎這個項目不使用安全組件:) –

+0

我沒有看到你實際登錄用戶的位置。例如,在哪裏更新令牌存儲? – Cerad

+0

@MaxP。我剛剛用我的security.yml更新了我的帖子。 –

回答

2

如果由於某種原因,你真的有需要手動登錄的用戶,則此方法在適當的時候添加到您的控制器和呼叫:

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'); 
} 

然而,在大多數情況下,現有的認證系統(或一個自定義警衛認證,https://symfony.com/doc/current/security/guard_authentication.html)會爲你做這個。

+0

非常感謝。這工作正常。但是我會看看Guard,我選擇了這種方式,因爲一眼就看不清楚,看起來有點過分了。 只是關於這個問題,爲什麼變量'$ token'是它返回一個空字符串? –

+0

令牌信息存儲在會話中。這是什麼讓應用程序記住誰登錄請求之間。我不知道你的意思是返回一個空字符串。 – Cerad

+0

是啊,夠公平的。我明白了。最後,我帶着守衛開發了它。我預料會更容易。幸運的是,這篇文章幫助了我很多。https://stackoverflow.com/questions/34250444/symfony-2-guard-component-and-a-normal-login-form –