FOSUserBundle - How to redirect already logged-in users when trying to access the login_path

前端 未结 5 2256
太阳男子
太阳男子 2020-12-19 14:02

Is it possible to perform an automatic redirect to the some route (i.e. /) for the specific route /login only for users that are AUTHENTICATED? and

相关标签:
5条回答
  • 2020-12-19 14:31

    Another solution based on the @nifr answer. Overwriting only the renderLogin function in your bundle controller. See also. How to use Bundle Inheritance to Override parts of a Bundle

    namespace MyProject\UserBundle\Controller;
    //namespace FOS\UserBundle\Controller;
    
     use Symfony\Component\HttpFoundation\RedirectResponse;
     use \FOS\UserBundle\Controller\SecurityController as BaseController;
    
     class SecurityController extends BaseController {
    
    /**
     * Renders the login template with the given parameters. Overwrite this function in
     * an extended controller to provide additional data for the login template.
     *
     * @param array $data
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
      protected function renderLogin(array $data) {
    
        if (true === $this->container->get('security.context')->isGranted('ROLE_USER')) {
            return new RedirectResponse($this->container->get('router')-  >generate('homeroute'));
        }
    
        $template = sprintf('FOSUserBundle:Security:login.html.%s', $this->container->getParameter('fos_user.template.engine'));
    
        return $this->container->get('templating')->renderResponse($template, $data);
      }
    
    }  
    
    0 讨论(0)
  • 2020-12-19 14:32

    NB : I'm using Symfony 3.0.4@dev

    This answer is based and the one that @nifr @mirk have provided and the comment of @Ronan.

    To prevent the user access to the login page I override the SecurityController like this :

    <?php
    
    namespace AppBundle\Controller;
    
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use FOS\UserBundle\Controller\SecurityController as BaseController;
    
    class SecurityController extends BaseController
    {
    
        /**
         * Renders the login template with the given parameters. Overwrite this function in
         * an extended controller to provide additional data for the login template.
         *
         * @param array $data
         *
         * @return \Symfony\Component\HttpFoundation\Response
         */
        protected function renderLogin (array $data)
        {
            // This little if do the trick
            if ($this->container->get('security.authorization_checker')->isGranted('ROLE_USER')) {
                return new RedirectResponse($this->container->get ('router')->generate ('app_generation_page'));
            }
    
            $template = sprintf ('FOSUserBundle:Security:login.html.twig');
            return $this->container->get ('templating')->renderResponse ($template, $data);
        }
    }
    

    I've also added it to the RegistrationController to do the exact same thing.

    Hope it will help some of you.

    0 讨论(0)
  • 2020-12-19 14:46

    As you are using FOSUserBundle the rendering of the login form takes place in SecurityController::renderLogin().

    The solution is bascially:

    • overriding the SecurityController
    • adding a check for the role IS_AUTHENTICATD_ANONYMOUSLY
    • redirecting the user to another page if the role was not found

    I assume you have already created a bundle extending FOSUserBundle which holds your User Entity.

    I assume this bundle is called YourUserBundle and is located at src/Your/Bundle/UserBundle.

    Now copy (not cut) the SecurityController

    vendor/friendsofsymfony/user-bundle/src/FOS/UserBundle/Controller/SecurityController.php
    

    to (in order to override the one provided by FOSUserBundle)

    src/Your/Bundle/UserBundle/Controller/SecurityController.php
    

    add the use-statement for RedirectResponse and edit the renderLogin() method like this:

    use Symfony\Component\HttpFoundation\RedirectResponse;
    
    // ...
    
    protected function renderLogin(array $data)
    {
        if (false === $this->container->get('security.context')->isGranted('IS_AUTHENTICATED_ANONYMOUSLY')) {
            return new RedirectResponse('/', 403);
        }
    
        $template = sprintf('FOSUserBundle:Security:login.html.%s', $this->container->getParameter('fos_user.template.engine'));
    
        return $this->container->get('templating')->renderResponse($template, $data);
    }
    

    Update

    Now instead of security.context use security.authorization_checker.

    http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements

    0 讨论(0)
  • 2020-12-19 14:50

    It seems to me overriding the rendering of the login form is providing an answer in the wrong place. The rendering of the login form is not the one responsible for login. It's a result of the login request. It could have other usages elsewhere in the future and you'd be breaking functionality for those situations.

    Overriding the login action seems better to me. That's the actual component responsible for handling the login request.

    To do that, override the login action in the Security Controller. Say you have a MyUserBundle in your MyProject project which extends the FOSUserBundle.

    <?php
    
    namespace MyProject\MyUserBundle\Controller;
    
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use FOS\UserBundle\Controller\SecurityController as BaseSecurityController;
    
    class SecurityController extends BaseSecurityController
    {
    
        /**
         * Overriding login to add custom logic.
         */
        public function loginAction(Request $request)
        {
            if( $this->container->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED') ){
    
                // IS_AUTHENTICATED_FULLY also implies IS_AUTHENTICATED_REMEMBERED, but IS_AUTHENTICATED_ANONYMOUSLY doesn't
    
                return new RedirectResponse($this->container->get('router')->generate('some_route_name_in_my_project', array())); 
                // of course you don't have to use the router to generate a route if you want to hard code a route
            }
    
            return parent::loginAction($request);
        }
    }
    
    0 讨论(0)
  • 2020-12-19 14:54

    I'm using the routing and security to enable this.

    #routing.yml
    index:
        path: /
        defaults: { _controller: AppBundle:Base:index }
        methods: [GET]
    
    login:
        path: /login
        defaults: { _controller: AppBundle:Security:login }
        methods: [GET]
    

    If a user is logged in, he get redirected to the dashboard. If not, he will see the login route.

    #security.yml
        access_control:
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/dashboard, role: ROLE_USER }
    

    Hope this helps you. :)

    0 讨论(0)
提交回复
热议问题