Связка пользователей - Как перенаправить уже вошедших в систему пользователей при попытке доступа к пути входа


Возможно ли выполнить автоматическое перенаправление на некоторый маршрут (т.Е./) для определенного маршрута /login только для пользователей, которые являются AUTHENTICATED? и как?

Я использую FOSUserBundle.

Это моя конфигурация безопасности:

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: ROLE_ADMIN

providers:
    fos_userbundle:
        id: fos_user.user_provider.username_email

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            csrf_provider: form.csrf_provider
            login_path: /accedi
            check_path: /login_check
            default_target_path: /
        oauth:
            resource_owners:
                facebook:           "/login/check-facebook"
                google:             "/login/check-google"
            login_path:        /accedi
            failure_path:      /accedi
            default_target_path: /

            oauth_user_provider:
                service: my_user_provider
        logout:
            path: /logout
            target: /
            invalidate_session: false
        anonymous:  ~
    login:
        pattern:  ^/login$
        security: false

        remember_me:
            key: "%secret%"
            lifetime: 31536000 # 365 days in seconds
            path: /
            domain: ~ 

    oauth_authorize:
        pattern:    ^/oauth/v2/auth
        form_login:
            provider: fos_userbundle
            check_path: _security_check
            login_path: _demo_login
        anonymous: true

    oauth_token:
        pattern:    ^/oauth/v2/token
        security:   false


access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/accedi$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/registrati, role: IS_AUTHENTICATED_ANONYMOUSLY }
Author: behramcelen, 2013-11-25

5 answers

При использовании FOSUserBundle отображение формы входа происходит в SecurityController::renderLogin().

Решение в основном таково:

  • переопределение контроллера безопасности
  • добавление проверки для роли IS_AUTHENTICATD_ANONYMOUSLY
  • перенаправление пользователя на другую страницу, если роль не была найдена

Я предполагаю, что вы уже создали пакет, расширяющий FOSUserBundle, который содержит вашу сущность User.

Я предполагаю, что этот пакет называется YourUserBundle и находится по адресу src/Your/Bundle/UserBundle.

Теперь скопируйте ( не вырезайте ) Контроллер безопасности

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

Для (чтобы переопределить тот, который предоставлен FOSUserBundle)

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

Добавьте инструкцию use-для RedirectResponse и отредактируйте метод renderLogin() следующим образом:

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);
}

Обновление

Теперь вместо security.context используйте security.authorization_checker.

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

 10
Author: nifr, 2017-09-07 14:35:48

Мне кажется, что переопределение отображения формы входа в систему дает ответ в неправильном месте. Отображение формы входа в систему не является ответственным за вход в систему. Это результат запроса на вход в систему. В будущем у него могут быть другие способы использования в других местах, и вы нарушите функциональность в этих ситуациях.

Переопределение действия входа в систему кажется мне лучше. Это фактический компонент, отвечающий за обработку запроса на вход.

Для этого переопределите действие входа в систему в контроллере безопасности. Допустим, у вас есть myuserbundle в вашем проекте MyProject, который расширяет 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);
    }
}
 7
Author: Prynz, 2014-03-04 10:54:46

ПРИМЕЧАНИЕ: Я использую Symfony 3.0.4@dev

Этот ответ основан и на том, который предоставил @nifr @mirk, и на комментарии @Ronan.

Чтобы запретить пользователю доступ к странице входа в систему, я переопределяю контроллер безопасности следующим образом:

<?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);
    }
}

Я также добавил его в контроллер регистрации, чтобы сделать то же самое.

Надеюсь, это поможет некоторым из вас.

 2
Author: Fikkwix, 2016-04-06 10:09:58

Другое решение, основанное на ответе @nifr. Перезапись только функции renderLogin в вашем контроллере пакетов. Смотрите также. Как использовать наследование пакета для переопределения частей пакета

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);
  }

}  
 1
Author: mirk, 2014-01-10 16:42:30

Я использую маршрутизацию и безопасность, чтобы включить это.

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

login:
    path: /login
    defaults: { _controller: AppBundle:Security:login }
    methods: [GET]

Если пользователь вошел в систему, он перенаправляется на панель мониторинга. Если нет, он увидит маршрут входа в систему.

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

Надеюсь, это поможет вам. :)

 -1
Author: kristof, 2016-09-21 13:32:49