6

我正在尝试使用 FOSUserBundle 实现注册。我希望管理员能够注册一个新用户,我只需将注册更改为防火墙路由(/admin/register 前缀)即可。

我创建了一个自定义注册表单类型并按照此处的说明将其注册为服务:https ://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/overriding_forms.md

然后我基于此连接到注册事件:https ://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/controller_events.md

我的听众看起来像这样:

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;


class RegistrationListener implements EventSubscriberInterface
{
    private $router;

    public function __construct(UrlGeneratorInterface $router)
    {
        $this->router = $router;
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
            FOSUserEvents::REGISTRATION_COMPLETED => 'onRegisterDone',
            FOSUserEvents::REGISTRATION_CONFIRMED => 'onRegisterDone',
            FOSUserEvents::RESETTING_RESET_COMPLETED => 'onRegisterDone',
        );
    }

    public function onRegisterDone(FilterUserResponseEvent $event)
    {
        $url = $this->router->generate('admin_panel');

        //$event->setResponse(new RedirectResponse($url));
    }
}

FilterUserResponseEvent 没有 setResponse 方法,所以我只是让它运行。我认为订阅此事件会覆盖默认的 FOS\UserBundle\EventListener\AuthenticationListener 订阅事件并阻止用户登录,但新用户仍会登录。

是否可以阻止身份验证,或者我应该只是创建一个新表单来调用操作来调用用户管理器?

4

4 回答 4

5

有同样的问题,这对我有用。

在覆盖的注册控制器中注释掉这一行:

$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

public function registerAction(Request $request)
{
    /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
    $formFactory = $this->container->get('fos_user.registration.form.factory');
    /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
    $userManager = $this->container->get('fos_user.user_manager');
    /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
    $dispatcher = $this->container->get('event_dispatcher');

    $user = $userManager->createUser();
    $user->setEnabled(true);

    $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, new UserEvent($user, $request));

    $form = $formFactory->createForm();
    $form->setData($user);

    if ('POST' === $request->getMethod()) {
        $form->bind($request);

        if ($form->isValid()) {
            $event = new FormEvent($form, $request);
            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

            $userManager->updateUser($user);

            if (null === $response = $event->getResponse()) {
                $url = $this->container->get('router')->generate('fos_user_registration_confirmed');
                $response = new RedirectResponse($url);
            }

            //comment below line to prevent login user after registration
            //$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

            return $response;
        }
    }

    return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
            'form' => $form->createView(),
    ));
}
于 2013-09-25T09:02:28.777 回答
2

您还可以覆盖注册控制器来执行此操作。(https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/overriding_controllers.md

您只需删除一行$this->authenticateUser($user);,注册后用户将不会被认证。

仅删除此行的覆盖控制器不是一个好方法。但是,如果您无法覆盖正确的侦听器并在正确的时刻挂钩,那么它可能是尽快完成任务的最简单方法;-)

于 2013-06-11T11:52:00.707 回答
2

这就是我重定向到管理面板的方法。我使用了 REGISTRATION_SUCCESS 事件(它使用 FormEvent 而不是 FilterUserResponseEvent)。

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;


class RegistrationListener implements EventSubscriberInterface
{
    private $router;

    public function __construct(UrlGeneratorInterface $router)
    {
        $this->router = $router;
    }

    public static function getSubscribedEvents()
    {
        return array(
            FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
        );
    }

    public function onRegistrationSuccess(FormEvent $event)
    {
        $url = $this->router->generate('admin_users');
        $event->setResponse(new RedirectResponse($url));
    }
}

为了防止身份验证,我必须按照https://stackoverflow.com/a/23969485/5074443中的描述覆盖 AuthenticationListener 。这是我的 AuthenticationListener:

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\EventListener\AuthenticationListener as FOSAuthenticationListener;

class AuthenticationListener extends FOSAuthenticationListener
{
    public static function getSubscribedEvents()
    {
        return array(
            // do not authenticate after registration
            // FOSUserEvents::REGISTRATION_COMPLETED => 'authenticate',
            // FOSUserEvents::REGISTRATION_CONFIRMED => 'authenticate'
            FOSUserEvents::RESETTING_RESET_COMPLETED => 'authenticate',
        );
    }
}
于 2015-07-03T09:48:53.697 回答
0

这是一个更简洁的版本,没有覆盖整个控制器:

是的,我知道注入整个容器是不好的做法,但这是一个快速的解决方案。:b

class RegistrationListener implements EventSubscriberInterface
{

protected $container;

public function __construct(ContainerInterface $container)
{
    $this->container = $container;
}

    public static function getSubscribedEvents()
    {
        return array(
            FOSUserEvents::REGISTRATION_CONFIRMED => ['onRegistrationConfirm', 999],
        );
    }

    public function onRegistrationConfirm(FilterUserResponseEvent $filterUserResponseEvent){
        $user = $filterUserResponseEvent->getUser();
        $user_manager = $this->container->get('fos_user.user_manager');
$user->setEnabled(false);
        $user->setLocked(true);
        $user_manager->updateUser($user);

    }


}
于 2015-07-01T14:23:17.390 回答