.. index::
single: Security; Named Encoders
How to Use A Different Password Encoder Algorithm Per User
==========================================================
Usually, the same password encoder is used for all users by configuring it
to apply to all instances of a specific class:
.. configuration-block::
.. code-block:: yaml
# config/packages/security.yaml
security:
# ...
encoders:
App\Entity\User:
algorithm: auto
cost: 12
.. code-block:: xml
.. code-block:: php
// config/packages/security.php
use App\Entity\User;
$container->loadFromExtension('security', [
// ...
'encoders' => [
User::class => [
'algorithm' => 'auto',
'cost' => 12,
],
],
]);
Another option is to use a "named" encoder and then select which encoder
you want to use dynamically.
In the previous example, you've set the ``auto`` algorithm for ``App\Entity\User``.
This may be secure enough for a regular user, but what if you want your admins
to have a stronger algorithm, for example ``auto`` with a higher cost. This can
be done with named encoders:
.. configuration-block::
.. code-block:: yaml
# config/packages/security.yaml
security:
# ...
encoders:
harsh:
algorithm: auto
cost: 15
.. code-block:: xml
.. code-block:: php
// config/packages/security.php
$container->loadFromExtension('security', [
// ...
'encoders' => [
'harsh' => [
'algorithm' => 'auto',
'cost' => '15',
],
],
]);
.. note::
If you are running PHP 7.2+ or have the `libsodium`_ extension installed,
then the recommended hashing algorithm to use is
:ref:`Sodium `.
This creates an encoder named ``harsh``. In order for a ``User`` instance
to use it, the class must implement
:class:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderAwareInterface`.
The interface requires one method - ``getEncoderName()`` - which should return
the name of the encoder to use::
// src/Acme/UserBundle/Entity/User.php
namespace Acme\UserBundle\Entity;
use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface, EncoderAwareInterface
{
public function getEncoderName()
{
if ($this->isAdmin()) {
return 'harsh';
}
return null; // use the default encoder
}
}
If you created your own password encoder implementing the
:class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`,
you must register a service for it in order to use it as a named encoder:
.. configuration-block::
.. code-block:: yaml
# config/packages/security.yaml
security:
# ...
encoders:
app_encoder:
id: 'App\Security\Encoder\MyCustomPasswordEncoder'
.. code-block:: xml
.. code-block:: php
// config/packages/security.php
// ...
use App\Security\Encoder\MyCustomPasswordEncoder;
$container->loadFromExtension('security', [
// ...
'encoders' => [
'app_encoder' => [
'id' => MyCustomPasswordEncoder::class,
],
],
]);
This creates an encoder named ``app_encoder`` from a service with the ID
``App\Security\Encoder\MyCustomPasswordEncoder``.
.. _`libsodium`: https://pecl.php.net/package/libsodium