Configuring the Encoder in security.yml
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.
Let's set some plain passwords! Where? In our fixtures! Open up fixtures.yml
and
scroll down. In theory, all we need to do is set the plainPassword
property.
The rest should happen auto-magically.
Add plainPassword:
and we'll keep with iliketurtles
, because I've gotten good
at typing that. And turtles are cool:
// ... lines 1 - 22 | |
AppBundle\Entity\User: | |
user_{1..10}: | |
// ... line 25 | |
plainPassword: iliketurtles |
Change over to your terminal and load your fixtures:
./bin/console doctrine:fixtures:load
Explosion!
No encoder has been configured for AppBundle\Entity\User
This is basically Symfony's way of saying:
Ryan, you didn't tell me how you want to encode the passwords. I can't read your mind - I'm just a PHP framework.
Remember how I kept saying we would encrypt the passwords with bcrypt
? Do you remember
actually configuring that anywhere? Nope! We need to do that.
Open security.yml
. Add an encoders
key, then AppBundle\Entity\User: bcrypt
:
// ... lines 1 - 2 | |
security: | |
encoders: | |
AppBundle\Entity\User: bcrypt | |
// ... lines 6 - 33 |
If you want, you can configure a few other options, but this is good enough.
Now Symfony knows how to encrypt our passwords. Try the fixtures again:
./bin/console doctrine:fixtures:load
No errors! So, that probably worked. Let's use it!
Checking the Encoded Password
In LoginFormAuthenticator
, we can finally add some real password checking!
How? By using that same UserPasswordEncoder
object.
Head back up to __construct
and add a new UserPasswordEncoder
argument. I'll
use my Option
+Enter
shortcut to setup that property for me:
// ... lines 1 - 10 | |
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder; | |
// ... lines 12 - 15 | |
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator | |
{ | |
// ... lines 18 - 20 | |
private $passwordEncoder; | |
public function __construct(FormFactoryInterface $formFactory, EntityManager $em, RouterInterface $router, UserPasswordEncoder $passwordEncoder) | |
{ | |
// ... lines 25 - 27 | |
$this->passwordEncoder = $passwordEncoder; | |
} | |
// ... lines 30 - 78 | |
} |
And because we're using autowiring for this service, we don't need to change anything
in services.yml
.
Now, in checkCredentials()
, replace the if
statement with
if ($this->passwordEncoder->isPasswordValid())
and pass that the User
object
and the plain-text password:
// ... lines 1 - 15 | |
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator | |
{ | |
// ... lines 18 - 58 | |
public function checkCredentials($credentials, UserInterface $user) | |
{ | |
// ... lines 61 - 62 | |
if ($this->passwordEncoder->isPasswordValid($user, $password)) { | |
return true; | |
} | |
// ... lines 66 - 67 | |
} | |
// ... lines 69 - 78 | |
} |
That'll take care of securely checking things.
Let's try it out: head to /login
. Use weaverryan+1@gmail.com
and iliketurtles
.
We're in! Password system check.
Ok team, that's it for authentication. You can build your authenticator to behave
however you want, and you can even have multiple authenticators. Oh, and if you
do want to use any of the built-in authentication systems, like the form_login
key I mentioned earlier - that's totally fine. Guard authentication takes more work,
but has more flexibility. If you want another example, we created a cool JSON web
token authenticator in our Symfony REST series.
Now, let's start locking down the system.
Hi guys, there is an '+' missing on line src/AppBundle/DataFixtures/ORM/fixtures.yml:25. Excelento work!