Skip to content

Commit 58d1cbb

Browse files
committed
Merge pull request #3405 from symfony/security_fix_extended
Changed sha1 into bcrypt continued...
2 parents d64258d + 473f8c1 commit 58d1cbb

File tree

3 files changed

+131
-139
lines changed

3 files changed

+131
-139
lines changed

book/security.rst

Lines changed: 37 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ see :doc:`/cookbook/security/form_login`.
660660
),
661661
),
662662
663-
**3. Be sure ``/login_check`` is behind a firewall**
663+
**3. Be sure /login_check is behind a firewall**
664664

665665
Next, make sure that your ``check_path`` URL (e.g. ``/login_check``)
666666
is behind the firewall you're using for your form login (in this example,
@@ -1206,19 +1206,6 @@ custom user class is that it implements the :class:`Symfony\\Component\\Security
12061206
interface. This means that your concept of a "user" can be anything, as long
12071207
as it implements this interface.
12081208

1209-
.. versionadded:: 2.1
1210-
In Symfony 2.1, the ``equals`` method was removed from ``UserInterface``.
1211-
If you need to override the default implementation of comparison logic,
1212-
implement the new :class:`Symfony\\Component\\Security\\Core\\User\\EquatableInterface`
1213-
interface.
1214-
1215-
.. note::
1216-
1217-
The user object will be serialized and saved in the session during requests,
1218-
therefore it is recommended that you `implement the \Serializable interface`_
1219-
in your user object. This is especially important if your ``User`` class
1220-
has a parent class with private properties.
1221-
12221209
Next, configure an ``entity`` user provider, and point it to your ``User``
12231210
class:
12241211

@@ -1278,7 +1265,7 @@ in plain text (whether those users are stored in a configuration file or in
12781265
a database somewhere). Of course, in a real application, you'll want to encode
12791266
your users' passwords for security reasons. This is easily accomplished by
12801267
mapping your User class to one of several built-in "encoders". For example,
1281-
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``,
12821269
do the following:
12831270

12841271
.. configuration-block::
@@ -1292,14 +1279,17 @@ do the following:
12921279
in_memory:
12931280
memory:
12941281
users:
1295-
ryan: { password: bb87a29949f3a1ee0559f8a57357487151281386, roles: 'ROLE_USER' }
1296-
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'
12971288
12981289
encoders:
12991290
Symfony\Component\Security\Core\User\User:
1300-
algorithm: sha1
1301-
iterations: 1
1302-
encode_as_base64: false
1291+
algorithm: bcrypt
1292+
cost: 12
13031293
13041294
.. code-block:: xml
13051295
@@ -1309,18 +1299,18 @@ do the following:
13091299
<provider name="in_memory">
13101300
<memory>
13111301
<user name="ryan"
1312-
password="bb87a29949f3a1ee0559f8a57357487151281386"
1302+
password="$2a$12$w/aHvnC/XNeDVrrl65b3dept8QcKqpADxUlbraVXXsC03Jam5hvoO"
13131303
roles="ROLE_USER" />
13141304
<user name="admin"
1315-
password="74913f5cd5f61ec0bcfdb775414c2fb3d161b620"
1305+
password="$2a$12$HmOsqRDJK0HuMDQ5Fb2.AOLMQHyNHGD0seyjU3lEVusjT72QQEIpW"
13161306
roles="ROLE_ADMIN" />
13171307
</memory>
13181308
</provider>
13191309
13201310
<encoder class="Symfony\Component\Security\Core\User\User"
1321-
algorithm="sha1"
1322-
iterations="1"
1323-
encode_as_base64="false" />
1311+
algorithm="bcrypt"
1312+
cost="12"
1313+
/>
13241314
</config>
13251315
13261316
.. code-block:: php
@@ -1333,11 +1323,11 @@ do the following:
13331323
'memory' => array(
13341324
'users' => array(
13351325
'ryan' => array(
1336-
'password' => 'bb87a29949f3a1ee0559f8a57357487151281386',
1326+
'password' => '$2a$12$w/aHvnC/XNeDVrrl65b3dept8QcKqpADxUlbraVXXsC03Jam5hvoO',
13371327
'roles' => 'ROLE_USER',
13381328
),
13391329
'admin' => array(
1340-
'password' => '74913f5cd5f61ec0bcfdb775414c2fb3d161b620',
1330+
'password' => '$2a$12$HmOsqRDJK0HuMDQ5Fb2.AOLMQHyNHGD0seyjU3lEVusjT72QQEIpW',
13411331
'roles' => 'ROLE_ADMIN',
13421332
),
13431333
),
@@ -1346,77 +1336,36 @@ do the following:
13461336
),
13471337
'encoders' => array(
13481338
'Symfony\Component\Security\Core\User\User' => array(
1349-
'algorithm' => 'sha1',
1350-
'iterations' => 1,
1351-
'encode_as_base64' => false,
1339+
'algorithm' => 'bcrypt',
1340+
'iterations' => 12,
13521341
),
13531342
),
13541343
));
13551344
1356-
By setting the ``iterations`` to ``1`` and the ``encode_as_base64`` to false,
1357-
the password is simply run through the ``sha1`` algorithm one time and without
1358-
any extra encoding. You can now calculate the hashed password either programmatically
1359-
(e.g. ``hash('sha1', 'ryanpass')``) or via some online tool like `functions-online.com`_
1360-
1361-
.. tip::
1362-
1363-
Supported algorithms for this method depend on your PHP version.
1364-
A full list is available calling the PHP function :phpfunction:`hash_algos`.
1365-
1366-
If you're creating your users dynamically (and storing them in a database),
1367-
you can use even tougher hashing algorithms and then rely on an actual password
1368-
encoder object to help you encode passwords. For example, suppose your User
1369-
object is ``Acme\UserBundle\Entity\User`` (like in the above example). First,
1370-
configure the encoder for that user:
1371-
1372-
.. configuration-block::
1373-
1374-
.. code-block:: yaml
1375-
1376-
# app/config/security.yml
1377-
security:
1378-
# ...
1379-
1380-
encoders:
1381-
Acme\UserBundle\Entity\User: sha512
1382-
1383-
.. code-block:: xml
1384-
1385-
<!-- app/config/security.xml -->
1386-
<config>
1387-
<!-- ... -->
1388-
1389-
<encoder class="Acme\UserBundle\Entity\User" algorithm="sha512" />
1390-
</config>
1345+
.. versionadded:: 2.2
1346+
The BCrypt encoder was introduced in Symfony 2.2.
13911347

1392-
.. code-block:: php
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.
13931351

1394-
// app/config/security.php
1395-
$container->loadFromExtension('security', array(
1396-
// ...
1397-
'encoders' => array(
1398-
'Acme\UserBundle\Entity\User' => 'sha512',
1399-
),
1400-
));
1352+
.. include:: /cookbook/security/_ircmaxwell_password-compat.rst.inc
14011353

1402-
In this case, you're using the stronger ``sha512`` algorithm. Also, since
1403-
you've simply specified the algorithm (``sha512``) as a string, the system
1404-
will default to hashing your password 5000 times in a row and then encoding
1405-
it as base64. In other words, the password has been greatly obfuscated so
1406-
that the hashed password can't be decoded (i.e. you can't determine the password
1407-
from the hashed password).
1354+
Supported algorithms for this method depend on your PHP version. A full list
1355+
is available by calling the PHP function :phpfunction:`hash_algos`.
14081356

14091357
.. versionadded:: 2.2
14101358
As of Symfony 2.2 you can also use the :ref:`PBKDF2 <reference-security-pbkdf2>`
1411-
and :ref:`BCrypt <reference-security-bcrypt>` password encoders.
1359+
password encoder.
14121360

14131361
Determining the Hashed Password
14141362
...............................
14151363

1416-
If you have some sort of registration form for users, you'll need to be able
1417-
to determine the hashed password so that you can set it on your user. No
1418-
matter what algorithm you configure for your user object, the hashed password
1419-
can always be determined in the following way from a controller::
1364+
If you're storing users in the database and you have some sort of registration
1365+
form for users, you'll need to be able to determine the hashed password so
1366+
that you can set it on your user before inserting it. No matter what algorithm
1367+
you configure for your user object, the hashed password can always be determined
1368+
in the following way from a controller::
14201369

14211370
$factory = $this->get('security.encoder_factory');
14221371
$user = new Acme\UserBundle\Entity\User();
@@ -1425,6 +1374,10 @@ can always be determined in the following way from a controller::
14251374
$password = $encoder->encodePassword('ryanpass', $user->getSalt());
14261375
$user->setPassword($password);
14271376

1377+
In order for this to work, just make sure that you have the encoder for your
1378+
user class (e.g. ``Acme\UserBundle\Entity\User``) configured under the ``encoders``
1379+
key in ``app/config/security.yml``.
1380+
14281381
.. caution::
14291382

14301383
When you allow a user to submit a plaintext password (e.g. registration
@@ -2077,5 +2030,4 @@ Learn more from the Cookbook
20772030
.. _`JMSSecurityExtraBundle`: http://jmsyst.com/bundles/JMSSecurityExtraBundle/1.2
20782031
.. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle
20792032
.. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php
2080-
.. _`functions-online.com`: http://www.functions-online.com/sha1.html
20812033
.. _`Timing attack`: http://en.wikipedia.org/wiki/Timing_attack
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.. caution::
2+
3+
If you're using PHP 5.4 or lower, you'll need to install the ``ircmaxell/password-compat``
4+
library via Composer in order to be able to use the ``bcrypt`` encoder:
5+
6+
.. code-block:: json
7+
8+
{
9+
"require": {
10+
...
11+
"ircmaxell/password-compat": "~1.0.3"
12+
}
13+
}

0 commit comments

Comments
 (0)