Más configuración de form_login
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeUtilizar form_login no es tan flexible como una clase de autentificador personalizada... aunque se pueden configurar muchas cosas.
Por ejemplo, ahora mismo, no comprueba nuestro token CSRF. Habilita eso diciendo enable_csrf: true:
| security: | |
| // ... lines 2 - 16 | |
| firewalls: | |
| // ... lines 18 - 20 | |
| main: | |
| // ... lines 22 - 24 | |
| form_login: | |
| // ... lines 26 - 29 | |
| enable_csrf: true | |
| // ... lines 31 - 54 |
¡Eso es! En las opciones, cuando activas la protección CSRF, busca un campo oculto llamado _csrf_token con la cadena authenticate utilizada para generarlo. Afortunadamente, en nuestra plantilla, ya estamos utilizando ambas cosas... así que esto va a funcionar.
Ver la lista completa de opciones
Y hay aún más formas de configurarlo. Recuerda: para obtener esta configuración, he ejecutado debug:config security... que muestra tu configuración actual, incluyendo los valores por defecto. Pero aquí no se muestran todas las opciones. Para ver una lista completa, ejecutaconfig:dump security.
symfony console config:dump security
En lugar de mostrar tu configuración actual, esto muestra una enorme lista de configuraciones de ejemplo. Esta es una lista mucho más grande... aquí está form_login. Mucho de esto lo hemos visto antes... pero success_handler y failure_handler son nuevos. Puedes buscarlos en la documentación para aprender a controlar lo que ocurre tras el éxito o el fracaso.
Pero también, más adelante, vamos a conocer una forma más global de engancharse al proceso de éxito o fracaso registrando un oyente de eventos.
Renderización de "último_nombre_de_usuario" en el formulario de inicio de sesión
De todos modos, ya no vamos a utilizar nuestro LoginFormAuthenticator, así que puedes eliminarlo.
Y... ¡Tengo buenas noticias! ¡El autentificador principal está haciendo una cosa que nuestra clase nunca hizo! En authenticate()... llama a getCredentials() para leer los datos POST. Déjame buscar "sesión"... ¡yup! Esto me llevó agetCredentials(). De todos modos, después de coger el correo electrónico enviado - en este código que se almacena como $credentials['username'] - guarda ese valor en la sesión.
Lo hace para que, si falla la autenticación, podamos leerlo y rellenar previamente la casilla del correo electrónico en el formulario de acceso.
¡Vamos a hacerlo! Ve a nuestro controlador: src/Controller/SecurityController.php. EsteAuthenticationUtils tiene otro método útil. Pasa una nueva variable a la plantilla llamada last_username -puedes llamarla last_email si quieres- y ponla en $authenticationUtils->getLastUsername():
| // ... lines 1 - 9 | |
| class SecurityController extends AbstractController | |
| { | |
| // ... lines 12 - 14 | |
| public function login(AuthenticationUtils $authenticationUtils): Response | |
| { | |
| return $this->render('security/login.html.twig', [ | |
| // ... line 18 | |
| 'last_username' => $authenticationUtils->getLastUsername(), | |
| ]); | |
| } | |
| // ... lines 22 - 29 | |
| } |
Una vez más, esto es sólo un ayudante para leer una clave específica de la sesión.
Ahora, en la plantilla - login.html.twig - aquí arriba en el campo de correo electrónico, añadevalue="{{ last_username }} ":
| // ... lines 1 - 4 | |
| {% block body %} | |
| <div class="container"> | |
| <div class="row"> | |
| <div class="login-form bg-light mt-4 p-4"> | |
| <form method="post" class="row g-3"> | |
| // ... lines 10 - 15 | |
| <div class="col-12"> | |
| // ... line 17 | |
| <input type="email" name="email" id="inputEmail" class="form-control" value="{{ last_username }}" required autofocus> | |
| </div> | |
| // ... lines 20 - 33 | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| {% endblock %} |
¡Genial! Si vamos a /login... ¡ya está ahí por haber rellenado el formulario hace un minuto! Si introducimos un correo electrónico diferente... ¡sí! Eso también se pega.
A continuación: volvamos a la autorización aprendiendo a denegar el acceso en un controlador... de varias maneras.
10 Comments
Hello,
When I use FormLoginAuthenticator(built-in) and try to login, the page is still redirecting login page. Authentication is succesfull but page is same.
We were coding redirect response in LoginFormAuthenticator(custom) as below. Did you configure anything for redirection in buil-in authenticator like custom authenticator? If not, why do I see same login page, do I have to configure authentictionsuccess also in buil-in?
Built-in Authenticator:
Hey Mahmut,
I didn't get why you send 2 different codes from
onAuthenticationSuccess().. .which is yours? I suppose you use the custom authenticator like that first code block, so I will assume that's your code. Maybe try to debug the flow withdd()? Make sure you hit thatreturn new RedirectResponse($this->router->generate('app_main_homepage',['username' => $username]));line on the successful login. If not - most probably you hit the earlier redirect which isreturn new RedirectResponse($target);. Probably you need to tweak the logic in youronAuthenticationSuccess()to make sure you redirect users to correct pages.I hope that helps!
Cheers!
Hi Victor,
Sorry for confusing. I am using below code during error. I mean if ı use built-in authenticator, it is redirecting same login page.
However, my custom login authenticator is working well.
Hey Mahmut,
The built-in authenticator can be configured via the configuration, but if you need more flexibility - better to go with your own custom authenticator where you can do whatever you want. Still you can debug the flow using
dd()- that should help to understand the flow and why it does not work as expected for you.Cheers!
I do not get the pre-filled email input once I have logged out. Is this normal? Is it because the session data has been erased at logout?
Hey Francois,
You can totally ignore that
value={{ last_username }}of course if it's not something you need. But the idea behind this thing is to keep the last username user entered - useful when they have misprint their credentials, e.g. password so they don't need to retype the username again and try a different password. That's a common practice on may websites over the internet, but that's totally up to you. Of course when you log out going to the /logout URL - the session will be destroyed and you will not see thatlast_usernameanymore.Cheers!
how can we implement this if we kept using the old
loginFormAuthonticatoron theonAuthenticationFailuremethod?Hey @Soufiyane!
Are you referring to how to print the "last username" thing? If so, the 2 steps are:
1) In your custom authenticator, in
authenticate(), after reading the email, call:2) In your controller, read that value in the same way as see in this chapter :).
Let me know if that helps!
Cheers!
Hi. I stayed with the custom login in my project. Can you show me how to add
$authenticationUtils-> getLastUsername(), in this case? In case withoutform_login: it didn't work :)Hey Leszek,
You only need to inject the service
Symfony\Component\Security\Http\Authentication\AuthenticationUtilsinto your Controller's method, or in case you need it in your authenticator, you can add another argument constructor and inject it thereCheers!
"Houston: no signs of life"
Start the conversation!