FOSUserBundle – как перенаправить уже зарегистрированных пользователей при попытке доступа к login_path

Возможно ли автоматическое перенаправление на какой-либо маршрут (т. Е. /) Для конкретного маршрута /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 } 

Когда вы используете FOSUserBundle, рендеринг формы входа происходит в SecurityController::renderLogin() .

Решение основано:

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

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

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

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

 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

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

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

Для этого переопределите действие входа в Security Controller. Скажем, у вас есть 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); } } 

NB: я использую Symfony 3.0.4@dev

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

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

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

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

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

Другое решение, основанное на ответе @nifr. renderLogin только функции renderLogin в вашем контроллере 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); } } 

Для этого я использую маршрутизацию и безопасность.

 #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 } 

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