0

我正在使用 Symfony3 构建我的第一个 API 登录,但我在登录监听器上绊倒了。我希望在用户成功登录后立即触发一个事件,用于各种常用目的,例如写日志、生成令牌等。因为事情是通过 API 发生的,所以登录系统与经典系统有点不同Symfony 指南中描述的登录表单。从这个角度来看,我确信我错过了一些东西。

监听器初始化:

// 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,它与非常相似),

为什么当用户和密码有效并且发生登录时,侦听器不被视为有效事件来触发interactive_login事件?

4

1 回答 1

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)将为您执行此操作。

于 2017-08-30T14:11:15.920 回答