There is a site on Symfony2.8, registration and everything attached to it is done using the FOSUserBundle.

The essence of the question is as follows: it is impossible to perform nicely ( as here, for example ) redirect to the admin area after logging in the user with the admin role.

The start page is available only after authorization, "ugly execution" is registered.

/** * @Route("/", name="catalog.books.list", options={"expose": true}) */ public function listAction(Request $request) { $user = $this->getUser(); if ($user === null) { return $this->redirect('/login'); } /* $baseUrl = $this->get('request')->getSchemeAndHttpHost(); $currentUrl = $request->server->get('HTTP_REFERER'); $lastPath = substr($currentUrl, strpos($currentUrl, $baseUrl)); $lastPath = str_replace($baseUrl, '', $lastPath); // admin redirect to page 'admin.books' if($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN') && ($lastPath == '/login')) { return $this->redirect('admin/books'); } */ return $this->render('AppBundle:Frontend/Catalog:list.html.twig', [ 'defaultLayout' => $request->cookies->get('visibleLayout') ]); } 

security.yml file:

 security: encoders: AppBundle\Entity\User: algorithm: bcrypt role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: ROLE_ADMIN providers: fos_userbundle: id: fos_user.user_provider.username firewalls: main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager # if you are using Symfony < 2.8, use the following config instead: # csrf_provider: form.csrf_provider logout: path: /logout target: /login anonymous: true access_control: - { path: ^/js/, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register/*, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/demo, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/getPage, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/getAsset, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/previewPage, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin, role: ROLE_ADMIN } - { path: ^/_error/, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/view, role: [ ROLE_USER, ROLE_DEMO_USER ] } - { path: ^/notes/*, role: [ ROLE_USER, ROLE_DEMO_USER ] } - { path: ^/bookmarks/*, role: IS_AUTHENTICATED_FULLY } - { path: ^/search, role: [ ROLE_USER, ROLE_DEMO_USER ] } - { path: ^/*, allow_if: "not has_role('ROLE_DEMO_USER')" } access_denied_url: /login 

Settings of type always_use_default_target_path: false and default_target_path:/ were unsuccessful.

FOS controller extension:

 class SecurityController extends FOSSecurityController{ public function loginAction(Request $request){ $auth_checker = $this->get('security.authorization_checker'); $router = $this->get('router'); // 307: Internal Redirect if ($auth_checker->isGranted(['ROLE_ADMIN'])) { // SUPER_ADMIN roles go to the `admin_home` route return new RedirectResponse($router->generate('admin.books'), 307); } if ($auth_checker->isGranted('ROLE_USER')) { // Everyone else goes to the `home` route return $this->redirect('/'); } // Always call the parent unless you provide the ENTIRE implementation return parent::loginAction($request);}} 

But, he almost does not get here, after the login he will redirect immediately to "/" - home-page so to speak ...

Login form, for completeness:

 <form action="{{ path("fos_user_security_check") }}" method="post" id="login-from"> <input type="hidden" name="_csrf_token" value="{{ csrf_token }}" /> <label for="username" class="placeholder username"> <span>Email address</span> <input type="email" id="username" {# placeholder="Email address" #} name="_username" value="{{ last_username }}" tabindex="1" required="required"/> </label> <label for="password" class="placeholder"> <span>Password</span> <a href="{{ path('fos_user_resetting_request') }}" class="forgot">Forgot?</a> <input tabindex="2" type="password" id="password" name="_password" required="required" /> </label> <input type="checkbox" id="remember_me" class="remember_me" name="_remember_me" value="on" /> <label for="remember_me">Remember me</label> <div> <input tabindex="3" type="submit" id="_submit" name="_submit" value="Log in" /> <a href="{{ path("fos_user_registration_register") }}" class="submit">Create account</a> </div> </form> 

Maybe someone will have ideas about where you need to podshamanit?

  • In general, the question seemed to be solved with the help of LoginHandlers - Alenko Verzina
  • If possible, publish the solution found in response to your question . I am sure it will help many of your colleagues in the future. - Nicolas Chabanovsky

1 answer 1

Solution - extensions of default DefaultAuthenticationSuccessHandler

LoginSuccessHandler.php custom handler:

 namespace AppBundle\Handler; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Router; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; use Symfony\Component\Security\Http\HttpUtils; class LoginSuccessHandler extends DefaultAuthenticationSuccessHandler { protected $router; protected $authorizationChecker; public function __construct(Router $router, AuthorizationChecker $authorizationChecker, HttpUtils $httpUtils, array $options = array()) { $this->router = $router; $this->authorizationChecker = $authorizationChecker; parent::__construct($httpUtils, $options); } public function onAuthenticationSuccess(Request $request, TokenInterface $token) { $response = null; if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) { $response = new RedirectResponse($this->router->generate('admin.books')); } else if ($this->authorizationChecker->isGranted('ROLE_USER')) { $response = new RedirectResponse($this->router->generate('catalog.books.list')); } return $response; } } 

Fragment serviсes.yml

 authentication.handler.login_success_handler: class: AppBundle\Handler\LoginSuccessHandler arguments: ['@router', '@security.authorization_checker', '@security.http_utils', {}] 

Firewall in security.yml :

  firewalls: main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager success_handler: authentication.handler.login_success_handler # if you are using Symfony < 2.8, use the following config instead: # csrf_provider: form.csrf_provider logout: path: /logout target: /login anonymous: true 

Parental Handler (for the DefaultAuthenticationSuccessHandler.php picture) DefaultAuthenticationSuccessHandler.php

 namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\ParameterBagUtils; /** * Class with the default authentication success handling logic. * * @author Fabien Potencier <fabien@symfony.com> * @author Johannes M. Schmitt <schmittjoh@gmail.com> * @author Alexander <iam.asm89@gmail.com> */ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface { protected $httpUtils; protected $options; protected $providerKey; protected $defaultOptions = array( 'always_use_default_target_path' => false, 'default_target_path' => '/', 'login_path' => '/login', 'target_path_parameter' => '_target_path', 'use_referer' => false, ); /** * Constructor. * * @param HttpUtils $httpUtils * @param array $options Options for processing a successful authentication attempt */ public function __construct(HttpUtils $httpUtils, array $options = array()) { $this->httpUtils = $httpUtils; $this->setOptions($options); } /** * {@inheritdoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request)); } //... }