覆盖FOSUserBundle loginAction()以重定向到自定义路由

时间:2017-09-20 07:49:12

标签: symfony fosuserbundle

我正在使用FOSUserBundle开发Symfony 3.3.8项目。我分别为学生和提供者创建了两个注册页面和两个个人资料页面。现在我试图覆盖FOSUserBundle的loginAction()方法,我正在检查登录用户的角色。如果角色为ROLE_STUDENT我尝试在成功登录后将用户重定向到学生资料页面,如果角色为ROLE_PROVIDER,我希望用户在成功登录后重定向到提供者资料页面。这是我用loginAction()重写的SecurityController:

<?php

namespace Epita\HousingBundle\Controller;

use FOS\UserBundle\Controller\SecurityController as BaseController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

class SecurityController extends BaseController {

    /**
     * 
     */
    public function loginAction(Request $request) {
         /** @var $session \Symfony\Component\HttpFoundation\Session\Session */
        $session = $request->getSession();
        $key = '_security.main.target_path';

        $securityContext = $this->container->get('security.authorization_checker');
        if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
            $user = $this->getUser();            
        }

        if ($this->container->get('session')->has($key)) 
        {
           if ($this->get('security.authorization_checker')->isGranted('ROLE_STUDENT')) {
                return $this->redirectToRoute('student_profile');
             } else if ($this->get('security.authorization_checker')->isGranted('ROLE_PROVIDER')) {
                return $this->redirectToRoute('provider_profile');
             } 
        }   
        else{
            return $this->redirectToRoute('student_profile');
        }

        if (class_exists('\Symfony\Component\Security\Core\Security')) {
            $authErrorKey = Security::AUTHENTICATION_ERROR;
            $lastUsernameKey = Security::LAST_USERNAME;
        } else {
            // BC for SF < 2.6
            $authErrorKey = SecurityContextInterface::AUTHENTICATION_ERROR;
            $lastUsernameKey = SecurityContextInterface::LAST_USERNAME;
        }

        // get the error if any (works with forward and redirect -- see below)
        if ($request->attributes->has($authErrorKey)) {
            $error = $request->attributes->get($authErrorKey);
        } elseif (null !== $session && $session->has($authErrorKey)) {
            $error = $session->get($authErrorKey);
            $session->remove($authErrorKey);
        } else {
            $error = null;
        }

        if (!$error instanceof AuthenticationException) {
            $error = null; // The value does not come from the security component.
        }

        // last username entered by the user
        $lastUsername = (null === $session) ? '' : $session->get($lastUsernameKey);

        if ($this->has('security.csrf.token_manager')) {
            $csrfToken = $this->get('security.csrf.token_manager')->getToken('authenticate')->getValue();
        } else {
            // BC for SF < 2.4
            $csrfToken = $this->has('form.csrf_provider')
                ? $this->get('form.csrf_provider')->generateCsrfToken('authenticate')
                : null;
        }

        return $this->renderLogin(array(
            'last_username' => $lastUsername,
            'error' => $error,
            'csrf_token' => $csrfToken,
        ));

    }

    /**
     *
     * @param array $data
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function renderLogin(array $data)
    { 
        $template = sprintf('EpitaHousingBundle:Security:login.html.twig');

        return $this->container->get('templating')->renderResponse($template, $data);

    }

    public function checkAction()
    {
        throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
    }

    public function logoutAction()
    {
        throw new \RuntimeException('You must activate the logout in your security firewall configuration.');
    }
}

但是这个解决方案对我不起作用。我的猜测是我必须参加会议。既然我是新来的,任何人都可以帮助我吗?

提前致谢。如果您需要更多详细信息,请与我们联系。

1 个答案:

答案 0 :(得分:2)

以下是一些可能对您有用的代码。

1 - 这是Event / LoginSuccessHandler,你的逻辑在这个类

<?php

namespace AppBundle\Event;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;


class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{
    protected $router;
    protected $security;

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

    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        $url = 'homepage';

        if ($this->security->isGranted('ROLE_STUDENT')) {
            $url = 'student_route';
        }
        if ($this->security->isGranted('ROLE_PROVIDER')) {
            $url = 'provider_route';
        }

        $response = new RedirectResponse($this->router->generate($url));

        return $response;
    }
}

2 - 我们设置了监听services.yml

中登录事件的配置
login_success_handler:
    class: AppBundle\Event\LoginSuccessHandler
    arguments:
        - "@router"
        - "@security.authorization_checker"
        tags:
            - { name: 'monolog.logger', channel: 'security' }

3 - 那应该是它。试着告诉我是否有问题