我正在尝试使用FOSUserBundle实施注册。我希望管理员能够注册一个新用户,我只需将注册更改为防火墙路由(/ admin / register prefix)即可。
我创建了一个自定义注册表单类型,并按照此处的说明将其注册为服务: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订阅事件并阻止用户登录,但新用户仍然会登录。
是否可以阻止身份验证,或者我应该只创建一个新表单来调用操作来调用用户管理器?
答案 0 :(得分: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(),
));
}
答案 1 :(得分:2)
您也可以覆盖注册控制器来执行此操作。 (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/overriding_controllers.md)
您只需要删除一行$this->authenticateUser($user);
,注册后就不会对用户进行身份验证。
覆盖控制器仅删除此行不是一个好方法。但是如果你无法覆盖正确的倾听者并在正确的时刻勾选它,那么它可以是尽快完成任务的最简单方法; - )
答案 2 :(得分: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',
);
}
}
答案 3 :(得分: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);
}
}