Symfony FOS UserBundle - 阻止经过身份验证的用户访问登录,注册,重置

时间:2018-02-28 10:22:06

标签: symfony fosuserbundle symfony3.x

我正在使用Symfony和FOS UserBundle,我想阻止经过身份验证的用户访问登录,注册或密码重置页面。任何访问这些页面的尝试都应该导致重定向到主页。

我已经读过你可以复制控制器来进行这些更改,但这意味着当有更新并再次应用这些更改时手动更新复制的代码,这并不理想。

还有可能使用事件订阅者。这是我的实现,它可用于阻止注册表单,但我仍然可以访问重置页面和登录页面。

use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Bundle\FrameworkBundle\Routing\Router;

class FOSUserSubscriber implements EventSubscriberInterface
{

    /**
     * @var Router
     */
    protected $router;

    /**
     * @var TokenStorage
     */
    private $tokenStorage;

    public function __construct(Router $router, TokenStorage $tokenStorage)
    {
        $this->router = $router;
        $this->tokenStorage = $tokenStorage;
    }

    public static function getSubscribedEvents()
    {
        return array(
            FOSUserEvents::REGISTRATION_INITIALIZE => 'forwardToRouteIfUser',
            FOSUserEvents::RESETTING_RESET_REQUEST => 'forwardToRouteIfUser',
            FOSUserEvents::RESETTING_RESET_INITIALIZE => 'forwardToRouteIfUser', //['forwardToRouteIfUser',-100]
            FOSUserEvents::RESETTING_RESET_SUCCESS => 'forwardToRouteIfUser',
            FOSUserEvents::RESETTING_RESET_COMPLETED => 'forwardToRouteIfUser',
        );
    }

    public function forwardToRouteIfUser(GetResponseUserEvent $event)
    {
        if (!$this->tokenStorage->getToken()->isAuthenticated()) {
            return;
        }

        $url = $this->router->generate('home');

        $response = new RedirectResponse($url);

        $event->setResponse($response);
    }

}

Service.yml

Foo\BarBundle\EventListeners\FOSUserSubscriber:
    arguments: ['@router','@security.token_storage']
    tags:
        - { name: kernel.event_subscriber }

如果使用Controller确实是唯一的方法,请提供一个不涉及复制大块代码的示例。

版本:

    "friendsofsymfony/user-bundle": "^2.0",
    "symfony/symfony": "3.4.*",

1 个答案:

答案 0 :(得分:0)

您可以实际覆盖FOSUserBundle控制器,而无需在有新版本的FOSUserBundle时手动更新它们,方法是使用return parent::loginAction($request);

以下是SecurityController的示例,以防止已登录的用户访问登录页面:

// src/UserBundle/Controller/SecurityController.php

namespace UserBundle\Controller;

use FOS\UserBundle\Controller\SecurityController as BaseController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Controller managing the login (extends FOSUserBundle SecurityController)
 */
class SecurityController extends BaseController
{
    /**
     * Customize the login action, to redirect already logged in users
     * to the homepage
     * 
     * @param Request $request
     * @return Response
     */
    public function loginAction(Request $request)
    {
        /* If the user is already logged in, redirect him to the homepage */
        if ($this->get(Services::SECURITY_AUTHORIZATION_CHECKER)->isGranted('IS_AUTHENTICATED_REMEMBERED')) {

            /* Redirect the user to the homepage */
            return new RedirectResponse($this->generateUrl('homepage'));
        }

        /* Call the parent method */
        return parent::loginAction($request);
    }
}

您可以将其应用于RegistrationControllerResettingController