Как настроить access_control, чтобы запретить пользователям, имеющим ‘ROLE_USER’, путь доступа: ^/login после успешного входа в систему?

#symfony #security #symfony-4.2

#symfony #Безопасность #symfony-4.2

Вопрос:

В security.yaml файле мы определяем управление доступом для различных маршрутов и РОЛЕЙ, которые могут получить доступ к этому же маршруту.

Но как мы можем настроить пользователя, который вошел в систему, но не может вернуться на страницу / login, пока он не выйдет из системы и «ROLE_USER» не изменится на «anon».

Я новичок в Symfony 4.2.

Контроллер:

 namespace AppController;

use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;
use SymfonyComponentSecurityCoreAuthorizationAuthorizationCheckerInterface;
//use SymfonyComponentSecurityCoreExceptionAccessDeniedException;

class SecurityController extends AbstractController
{
    /**
     * @Route("/login", name="login")
     */
    public function login(Request $request, AuthenticationUtils $utils, AuthorizationCheckerInterface $authChecker)
    {
        // to check whether user is looged-in
        if ($authChecker->isGranted('IS_AUTHENTICATED_FULLY')) {
            die('Logged in user cannot access this page');
        }
        // get the login error if there is one
        $error = $utils->getLastAuthenticationError();

        // last username entered by the user
        $lastUsername = $utils->getLastUsername();
        return $this->render('security/login.html.twig', [
            'last_username' => $lastUsername,
            'error' => $error
            ]);
    }

    public function logout()
    {
        # code...
    }
  

Комментарии:

1. Не было бы лучше, если бы вы перенаправляли прошедших проверку подлинности пользователей со страницы входа на стартовую страницу (или любую соответствующую страницу)?

Ответ №1:

Вы не можете запретить доступ зарегистрированному пользователю к странице входа путем редактирования security.yml . Все пользователи приложения Symfony, независимо от того, вошли они в систему или нет, будут иметь базовую привилегию доступа: IS_AUTHENTICATED_ANONYMOUSLY и Symfony не имеет исключительной роли для пользователя, не вошедшего в систему.

Однако вы можете добиться того же, проверив, вошел пользователь в систему или нет в вашем контроллере, и выполнить перенаправление или выдать AccessDeniedException :

 public function login($name, AuthorizationCheckerInterface $authChecker)
{
    if ($authChecker->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw new AccessDeniedException('Logged in user cannot access this page');
    }

    // ...
}
  

Комментарии:

1. Какой класс для AccessDeniedException??

2. оператор if неверен. Это должно быть ‘if ($authChecker->isGranted(‘IS_AUTHENTICATED_FULLY’)) { создать новое исключение AccessDeniedException (‘Зарегистрированный пользователь не может получить доступ к этой странице’); }’

3. Хорошее место, я скопировал пример из Symfony doc и не редактировал его.

4. Какой класс для AccessDeniedException??

5. Вы упомянули перенаправление, и это намного лучший вариант, чем выдача исключения. С точки зрения UX я думаю, что ужасно путать аутентифицированного пользователя с AccessDeniedException .

Ответ №2:

Как я упоминал в комментариях, на мой взгляд, отправка AccessDeniedException уже зарегистрированному пользователю не является хорошим подходом. Что подумали бы ваши пользователи? Если я уже вошел в систему, почему я не могу получить доступ к странице, к которой я обычно могу получить доступ, даже если я не вошел в систему.

Поэтому я настоятельно рекомендую перенаправлять зарегистрированных пользователей при доступе к /login пути на стартовую страницу вашего приложения.

Просто адаптируйте блок if-condition в методе login вашего SecurityController :

 if ($authChecker->isGranted('IS_AUTHENTICATED_FULLY)) {
    $this->redirectToRoute('name of the route - replace with an appropriate value');
}
  

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