Chapters
33 Chapters
|
3:34:13
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
04.
The Login Form
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // 1.10.2
"doctrine/doctrine-bundle": "^1.6.10", // 1.10.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-time-bundle": "^1.8", // 1.8.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.0
"sensio/framework-extra-bundle": "^5.1", // v5.2.0
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.1.4
"symfony/cache": "^3.3|^4.0", // v4.1.4
"symfony/console": "^4.0", // v4.1.4
"symfony/flex": "^1.0", // v1.21.6
"symfony/framework-bundle": "^4.0", // v4.1.4
"symfony/lts": "^4@dev", // dev-master
"symfony/property-access": "^3.3|^4.0", // v4.1.4
"symfony/property-info": "^3.3|^4.0", // v4.1.4
"symfony/security-bundle": "^4.0", // v4.1.4
"symfony/serializer": "^3.3|^4.0", // v4.1.4
"symfony/twig-bundle": "^4.0", // v4.1.4
"symfony/web-server-bundle": "^4.0", // v4.1.4
"symfony/yaml": "^4.0", // v4.1.4
"twig/extensions": "^1.5" // v1.5.2
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/debug-bundle": "^3.3|^4.0", // v4.1.4
"symfony/dotenv": "^4.0", // v4.1.4
"symfony/maker-bundle": "^1.0", // v1.7.0
"symfony/monolog-bundle": "^3.0", // v3.3.0
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.1.4
"symfony/stopwatch": "^3.3|^4.0", // v4.1.4
"symfony/var-dumper": "^3.3|^4.0", // v4.1.4
"symfony/web-profiler-bundle": "^3.3|^4.0" // v4.1.4
}
}
27 Comments
Good morning or evening! I wonder if there is any chance to make a redirect to a specific page after a logout?
I tried this
` $this->redirect($this->generateUrl('security_logout', [
as well as $this->redirectToRoute(...) but that doesnt work. I use the configured logout flow through security.yaml
I know it's very edge-casy, but I want to log users out and redirect them if they are logged in while clicking on the "register" route. And while I'm writing this, I'm wondering how to log out procedurally without redirects... for example in a controller.
Hey Metin Ö.
I guess the easiest way is to use "LogoutEvent" or "logout success handler" depending on symfony version. You can read more here https://symfony.com/doc/cur...
Cheers!
So it'll be a back and forth flow
Hi, I created a login form almost exactly as in this tutorial. Works great. Now I need to have a separate LoginFormAuthenticator that grabs the user input and validates against an Ldap server, sort of an employee login with the goal being to skip the whole registration process allowing employees to use their active directory creds to authenticate. I installed the Ldap package, added a service, a separate user provider, firewall, routes and login form. Also, this application uses EasyAdmin, fyi. Is this possible to have two separate logins for authentication processed in the same application? So far, submitting the 'employee' login form doesn't submit any form data to anywhere that I can tell. Tried using http_basic_ldap and there seemed to be session conflicts between the two types of users, not exactly sure? Am I going about this from the wrong angle? I know it's a lot I really appreciate any help/suggestions.
Hey Brent!
Ah, sounds cool! Here are some pointers :).
> installed the Ldap package, added a service, a separate user provider, firewall, routes and login form
All good... maybe :). You may not need 2 separate firewalls. It depends on your app: will "normal users" and "ldap users" being viewing the same pages? My guess is "yes". In that case, you only want 1 firewall (only 1 firewall can be active per request, and the active one is chosen by matching a URL to the firewall's pattern, so if you have 2 firewalls, only 1 will be active for a specific page that both users need to go to). Anyways, this is 100% ok to do this - it just means that you have 2 different ways to log into the same security system (i.e. firewall).
> So far, submitting the 'employee' login form doesn't submit any form data to anywhere that I can tell.
I would probably create a custom authenticator for the Ldap authentication. Here's the idea:
* /login is your normal login form. It submits to /login/check (the URLs may not match, I'm just showing an example) and your "login form authenticator" knows to "support" and "act" on this URL.
* /login/employees is your employee login form. It submits to /login/employees/check and your "ldap login form authenticator" knows to support and act on this URL. Inside of this authenticator, you could use an Ldap service that you registered (if you follow the LDAP Symfony docs, registering a service is one of the steps) to find the user information in LDAP. Then you would return a User object (more on this User object below).
You could absolutely also use http_basic_ldap or even form_login_ldap - that gives you more functionality out of the box, I just find them a lot more magic (who is reading my credentials and what does the lookup look like?).
One last point: there is a question of should have have just 1 User class or 2 User classes. Having 2 can complicate things because wherever you have $this->getUser() in your app, you may be getting UserClass1 or UserClass2, and each may have different methods/properties. It depends on your app, but I typically prefer to have just 1 User class, which would be an entity in your case. If you do this, then your "ldap form login authenticator" would do this:
A) Fetch the info from the ldap server
B) Check the database to see if that User is in the database yet (this will make more sense in a second). If it is, just return it (maybe you update some data on it from LDAP if you want).
C) If the user doesn't exist yet, create it, set some data on it and persist/flush to the database. You might even set some custom roles - e.g. ROLE_HUMAN_RESOURCES - based on the permissions that user has in LDAP.
Let me know if this helps!
Cheers!
How is the user input on the login form (twig template) validated? If the user input is grabbed by an LoginFormAuthenticator which searches for an user by using a UserProvider, it's essential that the UserProvider doesn't allow SQL injections. Wouldn't it be better to validate the input via FormBuilder instead of using a Twig templalte without validation?
Hey Nino!
Sorry for my slow reply! Excellent question :).
> If the user input is grabbed by an LoginFormAuthenticator which searches for an user by using a UserProvider, it's essential that the UserProvider doesn't allow SQL injections
You're 100% correct. And the UserProvider (the Doctrine user provider) DOES protect against SQL injections by using the normal prepared statement queries. So, you're covered without thinking about it :). This is actually the same reason that you don't have to worry about SQL injections with forms. The form system will help validate "invalid" input (e.g. putting a string into a number field, hacking a choice element to add an option that doesn't exist, or any of your @Assert\ rules), but the form system in itself doesn't validate against SQL injections. The reason is that... it doesn't need to. When you use the ORM (i.e. when you're querying through your repository [as long as you're using :wildcards and setParameter() in your custom queries] and saving entity objects, everything uses prepared statements).
Let me know if that makes sense!
Cheers!
Why It's recommended to implement a basic form login, instead of using the formbuilder and render the form via {{form(form)}} etc ??
Hey ahmedbhs
That's a good question and the answer is because of a couple of reasons. First, the error messages come from a different part of the framework (Security component), so you can't just execute
{{ form_error(form.email) }}Second, you have to change the name of the CSRF token
and lastly because you may not be using the Form component in your application.
Cheers!
Then how form errors are displayed in twig ?
Wwhy we have to change the csrf token ?
Twig grabs the error from the form field which is set after validating the form itself. But, the login action is different, it's intercepted by Symfony. In other to access to the error message, you have to retrieve by calling
Symfony\Component\Security\Http\Authentication\AuthenticationUtils::getLastAuthenticationError()About the CSRF, you don't have to actually change the token but you have to use the same name you used for generating it when check if it's valid in the
LoginFormAuthenticatorCould we simply use bootstrap4 form theme here ?
# config/packages/twig.yaml
twig:
form_themes: ['bootstrap_4_layout.html.twig']
Hey Kaizoku,
Yes, you can! But unless you write form's HTML code yourself like we did in this screencast. But if you use Symfony Forms - just specify "form_themes" and Twig will automatically style your form with Bootstrap 4 theme - that's the power of Symfony Form component and its Twig integration :)
Cheers!
Could you tell me why i have message "no route found for "GET/login""?
Hey Kamil,
Hm, try to clear the cache first - does it help? If no, try to debug your routes with the next command:
$ bin/console debug:router
You can even grep by "login" if needed:
$ bin/console debug:router | grep login
Do you see the login route in the output?
Cheers!
Yea it helped. I think that in previous tutorials i didn't have to do that. Thank you so much
Hey Kamil,
If you're about clearing the cache - yeah, most of the time you don't need to do it when you're in dev env... but depending on whether you use virtualization tool e.g. Docker or no it might be a good idea to start with clearing the cache before thinking about something else :)
Cheers!
Hi! I'm following this tutorial for my project but after I created the SecurityController all my pages doesn't work anymore. Here is the log:
(5/5) RuntimeError
An exception has been thrown during the rendering of a template ("[Syntax Error] Expected PlainValue, got ''' at position 22 in method App\Controller\SecurityController::login() in C:\Users\Giaco\Desktop\TribunaleMinori\TribunaleMinori\config/routes\../../src/Controller/ (which is being imported from "C:\Users\Giaco\Desktop\TribunaleMinori\TribunaleMinori\config/routes/annotations.yaml"). Make sure annotations are installed and enabled.").
And this happen with every page not only with the /login page, can you help me?
Hey Gballocc7
I've seen only that error when you try to use single quotes on annotations, i.e
Can you double check that and let me know if that was the case?
Cheers!
Hi
It would be nice to see an updated version of this based on "make:auth"
Hey Dinu B.!
Yea, I added the fancier version of make:auth to MakerBundle shortly after releasing this tutorial :). But basically, what we are writing by hand in this tutorial is more or less identical to what you can now get from make:auth by select the "form login" option. So, you can simple use that to generate all of this code. Or, you can follow this tutorial if you want to learn a bit more about what that generated code does and how it works :).
Let me know if that makes sense!
Cheers!
thx for reply. U're right regarding make:auth, I wrote that when I was watching that episode and right after that things started to clarify. My coding style it's kinda old school but symfony changed my opinion. Keep doing what u're doing!
Ha! Awesome! Well, you did it the hard way... I mean the *right* way then - you coded up everything manually, which is the best way to master this stuff in my opinion. Keep up the good work yourself!
Cheers!
The promised make command is finally there:
MakerBundle 1.8: Instant User & Login Form Commands
https://symfony.com/blog/ne...
Hey Zoltan!
Yay! Thanks for sharing the link btw!
Cheers!
Hi again! :)
I have a question for you. In the last tutorials from Symfony 2 and 3, if I'm not wrong we were using the FOSUserBundle to manage this part and it was really helpful.
I used it too this bundle and now I'm trying to migrate from Symfony 3 to Symfony 4. I realised that in Symfony 3 I had to override the basic templates from the FOSUserBundle and as it says in https://symfony.com/doc/mas..., I could replace theses templates locating the new templates inside app/Resources/FOSUserBundle/views/whatever.html.twig.
My confussion comes when I tried to find the new location from theses templates I created and I want to keep using.
In the new file structure from Symfony 4, there is no more the folder project/app/, so I don't know where to locate theses files.
Could you explain me where I should put these files now in the new structure or how I should manage it now?
Hi Apr
In Symfony 4 you can override bundle templates by putting them into <your-project>/templates/bundles/<bundle-name>/<template>. For more information check this doc page https://symfony.com/doc/cur...
Hope this will help.
Cheers!
"Houston: no signs of life"
Start the conversation!