Skip to content

Commit dfa761b

Browse files
committed
[symfony#3356] Changing to use the bcrypt algorithm
Also removing one example (now possible with using bcrypt from the beginning) and related tweaks.
1 parent 3a7020c commit dfa761b

File tree

1 file changed

+42
-71
lines changed

1 file changed

+42
-71
lines changed

book/security.rst

Lines changed: 42 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,7 +1265,7 @@ in plain text (whether those users are stored in a configuration file or in
12651265
a database somewhere). Of course, in a real application, you'll want to encode
12661266
your users' passwords for security reasons. This is easily accomplished by
12671267
mapping your User class to one of several built-in "encoders". For example,
1268-
to store your users in memory, but obscure their passwords via ``sha1``,
1268+
to store your users in memory, but obscure their passwords via ``bcrypt``,
12691269
do the following:
12701270

12711271
.. configuration-block::
@@ -1279,14 +1279,17 @@ do the following:
12791279
in_memory:
12801280
memory:
12811281
users:
1282-
ryan: { password: bb87a29949f3a1ee0559f8a57357487151281386, roles: 'ROLE_USER' }
1283-
admin: { password: 74913f5cd5f61ec0bcfdb775414c2fb3d161b620, roles: 'ROLE_ADMIN' }
1282+
ryan:
1283+
password: $2a$12$w/aHvnC/XNeDVrrl65b3dept8QcKqpADxUlbraVXXsC03Jam5hvoO
1284+
roles: 'ROLE_USER'
1285+
admin:
1286+
password: $2a$12$HmOsqRDJK0HuMDQ5Fb2.AOLMQHyNHGD0seyjU3lEVusjT72QQEIpW
1287+
roles: 'ROLE_ADMIN'
12841288
12851289
encoders:
12861290
Symfony\Component\Security\Core\User\User:
1287-
algorithm: sha1
1288-
iterations: 1
1289-
encode_as_base64: false
1291+
algorithm: bcrypt
1292+
cost: 12
12901293
12911294
.. code-block:: xml
12921295
@@ -1296,18 +1299,18 @@ do the following:
12961299
<provider name="in_memory">
12971300
<memory>
12981301
<user name="ryan"
1299-
password="bb87a29949f3a1ee0559f8a57357487151281386"
1302+
password="$2a$12$w/aHvnC/XNeDVrrl65b3dept8QcKqpADxUlbraVXXsC03Jam5hvoO"
13001303
roles="ROLE_USER" />
13011304
<user name="admin"
1302-
password="74913f5cd5f61ec0bcfdb775414c2fb3d161b620"
1305+
password="$2a$12$HmOsqRDJK0HuMDQ5Fb2.AOLMQHyNHGD0seyjU3lEVusjT72QQEIpW"
13031306
roles="ROLE_ADMIN" />
13041307
</memory>
13051308
</provider>
13061309
13071310
<encoder class="Symfony\Component\Security\Core\User\User"
1308-
algorithm="sha1"
1309-
iterations="1"
1310-
encode_as_base64="false" />
1311+
algorithm="bcrypt"
1312+
cost="12"
1313+
/>
13111314
</config>
13121315
13131316
.. code-block:: php
@@ -1320,11 +1323,11 @@ do the following:
13201323
'memory' => array(
13211324
'users' => array(
13221325
'ryan' => array(
1323-
'password' => 'bb87a29949f3a1ee0559f8a57357487151281386',
1326+
'password' => '$2a$12$w/aHvnC/XNeDVrrl65b3dept8QcKqpADxUlbraVXXsC03Jam5hvoO',
13241327
'roles' => 'ROLE_USER',
13251328
),
13261329
'admin' => array(
1327-
'password' => '74913f5cd5f61ec0bcfdb775414c2fb3d161b620',
1330+
'password' => '$2a$12$HmOsqRDJK0HuMDQ5Fb2.AOLMQHyNHGD0seyjU3lEVusjT72QQEIpW',
13281331
'roles' => 'ROLE_ADMIN',
13291332
),
13301333
),
@@ -1333,71 +1336,35 @@ do the following:
13331336
),
13341337
'encoders' => array(
13351338
'Symfony\Component\Security\Core\User\User' => array(
1336-
'algorithm' => 'sha1',
1337-
'iterations' => 1,
1338-
'encode_as_base64' => false,
1339+
'algorithm' => 'bcrypt',
1340+
'iterations' => 12,
13391341
),
13401342
),
13411343
));
13421344
1343-
By setting the ``iterations`` to ``1`` and the ``encode_as_base64`` to false,
1344-
the password is simply run through the ``sha1`` algorithm one time and without
1345-
any extra encoding. You can now calculate the hashed password either programmatically
1346-
(e.g. ``hash('sha1', 'ryanpass')``) or via some online tool like `functions-online.com`_
1347-
1348-
.. tip::
1349-
1350-
Supported algorithms for this method depend on your PHP version.
1351-
A full list is available calling the PHP function :phpfunction:`hash_algos`.
1352-
1353-
.. caution::
1354-
1355-
The above example is not meaned for practical usage, it uses a weak hash
1356-
algorithm and it is only done to be able to generate the password easily. Using
1357-
:ref:`BCrypt <reference-security-bcrypt>` is a better option.
1358-
13591345
.. versionadded:: 2.2
13601346
The BCrypt encoder was introduced in Symfony 2.2.
13611347

1362-
If you're creating your users dynamically (and storing them in a database),
1363-
you can use even tougher hashing algorithms and then rely on an actual password
1364-
encoder object to help you encode passwords. For example, suppose your User
1365-
object is ``Acme\UserBundle\Entity\User`` (like in the above example). First,
1366-
configure the encoder for that user:
1367-
1368-
.. configuration-block::
1369-
1370-
.. code-block:: yaml
1348+
You can now calculate the hashed password either programmatically
1349+
(e.g. ``password_hash('ryanpass', PASSWORD_BCRYPT, array('cost' => 12));``)
1350+
or via some online tool.
13711351

1372-
# app/config/security.yml
1373-
security:
1374-
# ...
1375-
1376-
encoders:
1377-
Acme\UserBundle\Entity\User: bcrypt
1378-
1379-
.. code-block:: xml
1352+
.. caution::
13801353

1381-
<!-- app/config/security.xml -->
1382-
<config>
1383-
<!-- ... -->
1354+
If you're using PHP 5.4 or lower, you'll need to install the ``ircmaxell/password-compat``
1355+
library via Composer:
13841356

1385-
<encoder class="Acme\UserBundle\Entity\User" algorithm="bcrypt" />
1386-
</config>
1357+
.. code-block:: json
13871358
1388-
.. code-block:: php
1389-
1390-
// app/config/security.php
1391-
$container->loadFromExtension('security', array(
1392-
// ...
1393-
'encoders' => array(
1394-
'Acme\UserBundle\Entity\User' => 'bcrypt',
1395-
),
1396-
));
1359+
{
1360+
"require": {
1361+
"...": "all the other dependencies...",
1362+
"ircmaxell/password-compat": "~1.0.3"
1363+
}
1364+
}
13971365
1398-
In this case, you're using the strong ``bcrypt`` algorithm. This means that the
1399-
password has been greatly obfuscated so that the hashed password can't be
1400-
decoded (i.e. you can't determine the password from the hashed password).
1366+
Supported algorithms for this method depend on your PHP version. A full list
1367+
is available by calling the PHP function :phpfunction:`hash_algos`.
14011368

14021369
.. versionadded:: 2.2
14031370
As of Symfony 2.2 you can also use the :ref:`PBKDF2 <reference-security-pbkdf2>`
@@ -1406,10 +1373,11 @@ decoded (i.e. you can't determine the password from the hashed password).
14061373
Determining the Hashed Password
14071374
...............................
14081375

1409-
If you have some sort of registration form for users, you'll need to be able
1410-
to determine the hashed password so that you can set it on your user. No
1411-
matter what algorithm you configure for your user object, the hashed password
1412-
can always be determined in the following way from a controller::
1376+
If you're storing users in the database and you have some sort of registration
1377+
form for users, you'll need to be able to determine the hashed password so
1378+
that you can set it on your user before inserting it. No matter what algorithm
1379+
you configure for your user object, the hashed password can always be determined
1380+
in the following way from a controller::
14131381

14141382
$factory = $this->get('security.encoder_factory');
14151383
$user = new Acme\UserBundle\Entity\User();
@@ -1418,6 +1386,10 @@ can always be determined in the following way from a controller::
14181386
$password = $encoder->encodePassword('ryanpass', $user->getSalt());
14191387
$user->setPassword($password);
14201388

1389+
In order for this to work, just make sure that you have the encoder for your
1390+
user class (e.g. ``Acme\UserBundle\Entity\User``) configured under the ``encoders``
1391+
key in ``app/config/security.yml``.
1392+
14211393
.. caution::
14221394

14231395
When you allow a user to submit a plaintext password (e.g. registration
@@ -2070,5 +2042,4 @@ Learn more from the Cookbook
20702042
.. _`JMSSecurityExtraBundle`: http://jmsyst.com/bundles/JMSSecurityExtraBundle/1.2
20712043
.. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle
20722044
.. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php
2073-
.. _`functions-online.com`: http://www.functions-online.com/sha1.html
20742045
.. _`Timing attack`: http://en.wikipedia.org/wiki/Timing_attack

0 commit comments

Comments
 (0)