Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving the new named algorithms into their own cookbook entry #3533

Merged
merged 2 commits into from
Feb 4, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 3 additions & 71 deletions book/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1434,78 +1434,10 @@ or via some online tool.
Supported algorithms for this method depend on your PHP version. A full list
is available by calling the PHP function :phpfunction:`hash_algos`.

Named encoders
..............

.. versionadded:: 2.5
Named encoders were introduced in Symfony 2.5

Another option is to set the encoder dynamically on an instance basis.
In the previous example, you've set the ``sha512`` algorithm for ``Acme\UserBundle\Entity\User``.
This may be secure enough for a regular user, but what if you want your admins to have
a stronger algorithm? Let's say ``bcrypt``. This can be done with named encoders:

.. configuration-block::

.. code-block:: yaml

# app/config/security.yml
security:
# ...
encoders:
harsh:
algorithm: bcrypt
cost: 15

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:srv="http://symfony.com/schema/dic/services">

<config>
<!-- ... -->
<encoder class="harsh"
algorithm="bcrypt"
cost="15" />
</config>
</srv:container>

.. code-block:: php

// app/config/security.php
$container->loadFromExtension('security', array(
// ...
'encoders' => array(
'harsh' => array(
'algorithm' => 'bcrypt',
'cost' => '15'
),
),
));

Now you've created an encoder named ``harsh``. In order for a ``User`` instance to use it,
It must implement ``EncoderAwareInterface`` and have a method ``getEncoderName`` which returns the
name of the encoder to use::

// src/Acme/UserBundle/Entity/User.php
namespace Acme\UserBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface;
.. tip::

class User implements UserInterface, EncoderAwareInterface
{
public function getEncoderName()
{
if ($this->isAdmin()) {
return 'harsh';
}

return null; // use the default encoder
}
}
It's also possible to use different hashing algorithms on a user-by-user
basis. See :doc:`/cookbook/security/named-encoders` for more details.

Determining the Hashed Password
...............................
Expand Down
1 change: 1 addition & 0 deletions cookbook/map.rst.inc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
* :doc:`/cookbook/security/custom_authentication_provider`
* :doc:`/cookbook/security/target_path`
* :doc:`/cookbook/security/csrf_in_login_form`
* :doc:`/cookbook/security/named_encoders`

* **Serializer**

Expand Down
1 change: 1 addition & 0 deletions cookbook/security/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ Security
custom_authentication_provider
target_path
csrf_in_login_form
named_encoders
123 changes: 123 additions & 0 deletions cookbook/security/named_encoders.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
.. index::
single: Security; Named Encoders

How to Choose the Password Encoder Algorithm Dynamically
========================================================

.. versionadded:: 2.5
Named encoders were introduced in Symfony 2.5.

Usually, the same password encoder is used for all users by configuring it
to apply to all instances of a specific class:

# app/config/security.yml
security:
# ...
encoders:
Symfony\Component\Security\Core\User\User: sha512

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<config>
<!-- ... -->
<encoder class="Symfony\Component\Security\Core\User\User"
algorithm="sha512"
/>
</config>
</srv:container>

.. code-block:: php

// app/config/security.php
$container->loadFromExtension('security', array(
// ...
'encoders' => array(
'Symfony\Component\Security\Core\User\User' => array(
'algorithm' => 'sha512',
),
),
));

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 ``sha512`` algorithm for ``Acme\UserBundle\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 ``bcrypt``. This can be done with
named encoders:

.. configuration-block::

.. code-block:: yaml

# app/config/security.yml
security:
# ...
encoders:
harsh:
algorithm: bcrypt
cost: 15

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd"
>

<config>
<!-- ... -->
<encoder class="harsh"
algorithm="bcrypt"
cost="15" />
</config>
</srv:container>

.. code-block:: php

// app/config/security.php
$container->loadFromExtension('security', array(
// ...
'encoders' => array(
'harsh' => array(
'algorithm' => 'bcrypt',
'cost' => '15'
),
),
));

This creates an encoder named ``harsh``. In order for a ``User`` instance
to use it, the class must implement
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] the class must implement the ... interface.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-1

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, only because then it reads "must implement the EncoderAwareInterface interface" (double interface) :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. I didn't think of that.

:class:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderAwareInterface`.
The interface requires one method - ``getEncoderName`` - which should reutrn
the name of the encoder to use::

// src/Acme/UserBundle/Entity/User.php
namespace Acme\UserBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface;

class User implements UserInterface, EncoderAwareInterface
{
public function getEncoderName()
{
if ($this->isAdmin()) {
return 'harsh';
}

return null; // use the default encoder
}
}