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