src/Controller/SecurityController.php line 23

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Security\LoginFormAuthenticator;
  4. use App\Services\TwoFactorService;
  5. use LogicException;
  6. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  7. use Symfony\Component\HttpFoundation\Request;
  8. use Symfony\Component\HttpFoundation\Response;
  9. use Symfony\Component\Routing\Annotation\Route;
  10. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  11. class SecurityController extends AbstractController
  12. {
  13.     /**
  14.      * @Route("/login", name="app_login")
  15.      * @param AuthenticationUtils $authenticationUtils
  16.      * @param Request $request
  17.      * @param TwoFactorService $twoFactorService
  18.      * @return Response
  19.      */
  20.     public function login(
  21.         AuthenticationUtils $authenticationUtils,
  22.         Request $request,
  23.         TwoFactorService $twoFactorService
  24.     ): Response {
  25.         if ($this->getUser()) {
  26.             return $this->redirectToRoute("app_index");
  27.         }
  28.         $session = $request->getSession();
  29.         // Кнопка «Вернуться ко входу» на форме кода: гасим challenge и
  30.         // показываем обычную форму логина и пароля (#4049).
  31.         if ($request->query->getBoolean('restart')) {
  32.             $session->remove(LoginFormAuthenticator::SESSION_CHALLENGE);
  33.             return $this->redirectToRoute('app_login');
  34.         }
  35.         // get the login error if there is one
  36.         $error = $authenticationUtils->getLastAuthenticationError();
  37.         // last username entered by the user
  38.         $lastUsername = $authenticationUtils->getLastUsername();
  39.         // Живой challenge в сессии означает, что пароль уже принят и ждём код.
  40.         // Проверяем его именно здесь, а не по одному факту наличия ключа:
  41.         // токен мог истечь или исчерпать попытки, пока страница была открыта, —
  42.         // тогда форму кода рисовать нельзя, человека надо вернуть к паролю.
  43.         $challengeToken = (string)$session->get(LoginFormAuthenticator::SESSION_CHALLENGE, '');
  44.         if ($challengeToken !== '' && $twoFactorService->loadValidChallenge($challengeToken) !== null) {
  45.             // Приглашение ввести код приезжает сюда тем же механизмом, что и
  46.             // ошибки (иначе из guard-цепочки на страницу логина не вернуться),
  47.             // но ошибкой не является — красный блок на первом же шаге пугал бы
  48.             // зря. Отличаем по служебному ключу, шаблон покажет нейтральный текст.
  49.             if ($error !== null && $error->getMessageKey() === LoginFormAuthenticator::PROMPT_ENTER_CODE) {
  50.                 $error = null;
  51.             }
  52.             return $this->render('security/login_2fa.html.twig', [
  53.                 'error' => $error,
  54.                 'attempts_left' => $twoFactorService->attemptsLeft($challengeToken),
  55.                 'digits' => \App\Services\TotpService::digits(),
  56.             ]);
  57.         }
  58.         $session->remove(LoginFormAuthenticator::SESSION_CHALLENGE);
  59.         return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
  60.     }
  61.     /**
  62.      * @Route("/logout", name="app_logout")
  63.      */
  64.     public function logout()
  65.     {
  66.         throw new LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
  67.     }
  68. }