Php 在Symfony'中注册后禁用自动登录;福苏斯邦德酒店
使用最新的Symfony和FOSUserbundle,成功注册新用户后,用户将自动登录。我想阻止这一切。我的理由是,只有特殊用户才能注册新用户 我想我必须重写捆绑包的RegisterController中的registerAction,但我不知道如何重写 我尝试了:,但它似乎已经过时,没有使用此方法创建用户 如有任何提示,我们将不胜感激 编辑: 我发现我没有正确创建子捆绑包。我还必须创建自己的EventListener。现在,当我覆盖Php 在Symfony'中注册后禁用自动登录;福苏斯邦德酒店,php,symfony,fosuserbundle,Php,Symfony,Fosuserbundle,使用最新的Symfony和FOSUserbundle,成功注册新用户后,用户将自动登录。我想阻止这一切。我的理由是,只有特殊用户才能注册新用户 我想我必须重写捆绑包的RegisterController中的registerAction,但我不知道如何重写 我尝试了:,但它似乎已经过时,没有使用此方法创建用户 如有任何提示,我们将不胜感激 编辑: 我发现我没有正确创建子捆绑包。我还必须创建自己的EventListener。现在,当我覆盖FOSUserEvents::REGISTRATION\u S
FOSUserEvents::REGISTRATION\u SUCCESS
事件时,它就可以工作了
奇怪的是,当我使用FOSUserEvents::REGISTRATION\u COMPLETED
事件时,我的bundle和FOSUserbundle两个事件都被调度,因此用户被重定向到正确的站点,但作为新用户登录
编辑2:
这就是我的听众:
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
FOSUserEvents::REGISTRATION_COMPLETED => 'onRegistrationCompleted',
);
}
public function onRegistrationSuccess(FormEvent $event)
{
$url = $this->router->generate('admin');
$event->setResponse(new RedirectResponse($url));
}
public function onRegistrationCompleted(FilterUserResponseEvent $event)
{
}
我在
REGISTRATION\u SUCCESS
事件中设置重定向,并且REGISTRATION\u COMPLETED
为空。使用调试器,我可以验证是否调用了我自己的侦听器事件,但也调用了原始事件 您可以使用侦听器解决此问题,在fos用户捆绑包中,它在注册后对用户进行身份验证
文件:friendsofsymfony/user bundle/EventListener/AuthenticationListener.php
类:FOS\UserBundle\EventListener\AuthenticationListener
如果您选中该类,您将看到它跟踪注册\u完成的事件
在authenticationlistener
中,它在触发logInUser
函数后发送事件。因此,您必须注销监听器中的用户,该用户订阅“注册已完成”
您可以检查是否将侦听器写入注销用户
注意:在每个注册过程中,这可能不是登录注销用户的好方法,但是如果您使用fosuserbundle最简单的方法和最小占用空间,那么就是这样,如果已经有一个yml配置不存在,实际上在代码中没有yml配置的方向。所以这种方法就是最小占用空间
try {
$this->loginManager->logInUser($this->firewallName, $event->getUser(), $event->getResponse());
$eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($event->getUser(), $event->getRequest()));
} catch (AccountStatusException $ex) {
// We simply do not authenticate users which do not pass the user
// checker (not enabled, expired, etc.).
}
您就快到了,正如您所说,您的侦听器已被调用,但顺序不正确,因此您需要使您的侦听器在默认侦听器之前执行
为了实现这一改变
FOSUserEvents::注册成功=>
“onRegistrationSuccess”
到
FOSUserEvents::注册成功=>
['onRegistrationSuccess',-10]
注意这里的-10,这会更改侦听器的优先级
class RegistrationSuccessEventListener implements EventSubscriberInterface{
private $router;
public function __construct(UrlGeneratorInterface $router){
$this->router = $router;
}
public static function getSubscribedEvents()
{
//this will be called before
return array(
FOSUserEvents::REGISTRATION_SUCCESS => ['onUserRegistrationSuccess', -30],
);
}
/**
* @param FormEvent $event
* When the user registration is completed redirect
* to the employee list page and avoid the automatic
* mail sending and user authentication that happends
*
*/
public function onUserRegistrationSuccess(FormEvent $event){
$url = $this->router->generate('employees_list');
$event->setResponse(new RedirectResponse($url));
}
}
我在FOSBundle版本中使用symfony 2.8
friendsofsymfony/用户捆绑开发主机1f97ccf Symfony FOSUserBundle
根据composer info
EDIT:的输出,这项技术适用于Symfony 3.3,我不知道它是否适用于较低版本
正确的方法是创建一个
您还可以:通过在app/config.yml文件或bundle config文件上添加一个名称相同的新服务来覆盖该服务:fos_user.listener.authentication,并像下面所做的那样将新类添加到其中,然后添加此
下面是如何在使用编译器传递技术注册新用户时覆盖自动日志记录
编译器通过
namespace arpa3\UserBundle\DependencyInjection;
use arpa3\UserBundle\EventListener\AuthenticationListener;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class OverrideServiceCompilerPass implements CompilerPassInterface {
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('fos_user.listener.authentication');
$definition->setClass(AuthenticationListener::class);
}
}
服务覆盖
namespace arpa3\UserBundle\EventListener;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Security\LoginManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
class AuthenticationListener implements EventSubscriberInterface
{
/**
* @var LoginManagerInterface
*/
private $loginManager;
/**
* @var string
*/
private $firewallName;
/**
* AuthenticationListener constructor.
*
* @param LoginManagerInterface $loginManager
* @param string $firewallName
*/
public function __construct(LoginManagerInterface $loginManager, $firewallName)
{
$this->loginManager = $loginManager;
$this->firewallName = $firewallName;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
// You can disable any of them or all of them as you want
//FOSUserEvents::REGISTRATION_COMPLETED => 'authenticate',
//FOSUserEvents::REGISTRATION_CONFIRMED => 'authenticate',
//FOSUserEvents::RESETTING_RESET_COMPLETED => 'authenticate',
);
}
/**
* @param FilterUserResponseEvent $event
* @param string $eventName
* @param EventDispatcherInterface $eventDispatcher
*/
public function authenticate(FilterUserResponseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
{
try {
$this->loginManager->logInUser($this->firewallName, $event->getUser(), $event->getResponse());
$eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($event->getUser(), $event->getRequest()));
} catch (AccountStatusException $ex) {
// We simply do not authenticate users which do not pass the user
// checker (not enabled, expired, etc.).
}
}
}
namespace arpa3\UserBundle;
use arpa3\UserBundle\DependencyInjection\OverrideServiceCompilerPass;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class arpa3UserBundle extends Bundle {
public function getParent () {
return 'FOSUserBundle';
}
/**
*
* This injects a Compiler Pass that is used to override the automatic login after registration of a new user
* We have done this in order to disable the "by default" behaviour given that only admins can register users
* and logging in into the newly created account automatically is just not a desired behaviour
*
* @param ContainerBuilder $container
*/
public function build ( ContainerBuilder $container ) {
parent ::build( $container );
$container -> addCompilerPass( new OverrideServiceCompilerPass() );
}
}
在主捆绑文件上注册编译器密码
namespace arpa3\UserBundle\EventListener;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Security\LoginManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
class AuthenticationListener implements EventSubscriberInterface
{
/**
* @var LoginManagerInterface
*/
private $loginManager;
/**
* @var string
*/
private $firewallName;
/**
* AuthenticationListener constructor.
*
* @param LoginManagerInterface $loginManager
* @param string $firewallName
*/
public function __construct(LoginManagerInterface $loginManager, $firewallName)
{
$this->loginManager = $loginManager;
$this->firewallName = $firewallName;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
// You can disable any of them or all of them as you want
//FOSUserEvents::REGISTRATION_COMPLETED => 'authenticate',
//FOSUserEvents::REGISTRATION_CONFIRMED => 'authenticate',
//FOSUserEvents::RESETTING_RESET_COMPLETED => 'authenticate',
);
}
/**
* @param FilterUserResponseEvent $event
* @param string $eventName
* @param EventDispatcherInterface $eventDispatcher
*/
public function authenticate(FilterUserResponseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
{
try {
$this->loginManager->logInUser($this->firewallName, $event->getUser(), $event->getResponse());
$eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($event->getUser(), $event->getRequest()));
} catch (AccountStatusException $ex) {
// We simply do not authenticate users which do not pass the user
// checker (not enabled, expired, etc.).
}
}
}
namespace arpa3\UserBundle;
use arpa3\UserBundle\DependencyInjection\OverrideServiceCompilerPass;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class arpa3UserBundle extends Bundle {
public function getParent () {
return 'FOSUserBundle';
}
/**
*
* This injects a Compiler Pass that is used to override the automatic login after registration of a new user
* We have done this in order to disable the "by default" behaviour given that only admins can register users
* and logging in into the newly created account automatically is just not a desired behaviour
*
* @param ContainerBuilder $container
*/
public function build ( ContainerBuilder $container ) {
parent ::build( $container );
$container -> addCompilerPass( new OverrideServiceCompilerPass() );
}
}
还有其他方法,例如覆盖config.yml上的身份验证服务,但上面的解决方案是我找到的最干净、最可维护的解决方案。实际上,不需要做任何这些。如果use\u authentication\u listener
设置为false,则从容器中删除fos\u user.listener.authentication
服务
请参见FOS\UserBundle\DependencyInjection\FOSUserExtension
此信息也包含在文档中。文档看起来不错。有许多方法可以覆盖bundles文件。您是否正在制作文档中的userbundle的“子”文件?还是别的什么?另外,如果您在管理员之后只能创建用户,那么可能FOSuserBundle的注册端是错误的位?当然,在管理员防火墙后面创建一个CRUD来管理用户会更好吗?@DevDonkey:你是对的,我没有正确创建捆绑包。现在好像有用了。也许创建一个CRUD会更容易。酷,很高兴你把它整理好了。我不希望用户首先登录。这就是为什么我会覆盖新用户在默认情况下通过身份验证的REGISTRATION\u COMPLETED
事件。你是说你说覆盖事件时扩展了捆绑包吗?哦,我刚刚学会了通过服务覆盖服务/侦听器的技术。yml这很酷:)谢谢你的回答,不幸的是,我现在无法测试它,因为项目已经完成。