8000 Changed sha1 into bcrypt continued... by weaverryan · Pull Request #3405 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

Changed sha1 into bcrypt continued... #3405

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

Merged
merged 6 commits into from
Jan 21, 2014
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
[#3356] Moving serialize and Equatable logic further down for clarity
  • Loading branch information
weaverryan committed Jan 2, 2014
commit 0e6cc4d2af6213d08ccadf218cb6d3dbbeba0802
89 changes: 54 additions & 35 deletions cookbook/security/entity_provider.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The Data Model
--------------

For the purpose of this cookbook, the ``AcmeUserBundle`` bundle contains a
``User`` entity class with the following fields: ``id``, ``username``, ``salt``,
``User`` entity class with the following fields: ``id``, ``username``,
``password``, ``email`` and ``isActive``. The ``isActive`` field tells whether
or not the user account is active.

Expand Down Expand Up @@ -77,11 +77,6 @@ focus on the most important methods that come from the
*/
private $username;

/**
* @ORM\Column(type="string", length=32)
*/
private $salt;

/**
* @ORM\Column(type="string", length=64)
*/
Expand All @@ -100,7 +95,6 @@ focus on the most important methods that come from the
public function __construct()
{
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}

/**
Expand All @@ -116,7 +110,7 @@ focus on the most important methods that come from the
*/
public function getSalt()
{
return $this->salt;
return null;
}

/**
Expand Down Expand Up @@ -192,33 +186,15 @@ interface forces the class to implement the five following methods:

* ``getRoles()``,
* ``getPassword()``,
* ``getSalt()``,
* ``getPassword()``,
* ``getUsername()``,
* ``eraseCredentials()``

For more details on each of these, see :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface`.

.. sidebar:: What is the importance of serialize and unserialize?

The :phpclass:`Serializable` interface and its ``serialize`` and ``unserialize``
methods have been added to allow the ``User`` class to be serialized
to the session. This may or may not be needed depending on your setup,
but it's probably a good idea. The ``id`` is the most important value
that needs to be serialized because the
:method:`Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider::refreshUser`
method reloads the user on each request by using the ``id``. In practice,
this means that the User object is reloaded from the database on each
request using the ``id`` from the serialized object. This makes sure
all of the User's data is fresh.

Symfony also uses the ``username``, ``salt``, and ``password`` to verify
that the User has not changed between requests. Failing to serialize
these may cause you to be logged out on each request. If your User implements
:class:`Symfony\\Component\\Security\\Core\\User\\EquatableInterface`,
then instead of these properties being checked, your ``isEqualTo`` method
is simply called, and you can check whatever properties you want. Unless
you understand this, you probably *won't* need to implement this interface
or worry about it.
If you're curious about the ``serialize`` method or are looking for details
on the logic of seeing if the User stored in the session is the same as the
one stored in the database, see :ref:`cookbook-security-serialize-equatable`.

Below is an export of the ``User`` table from MySQL with user ``admin`` and
password ``admin`` (which has been encoded). For details on how to create
Expand All @@ -227,11 +203,11 @@ user records and encode their password, see :ref:`book-security-encoding-user-pa
.. code-block:: bash

$ mysql> select * from acme_users;
+----+----------+------+------------------------------------------+--------------------+-----------+
| id | username | salt | password | email | is_active |
+----+----------+------+------------------------------------------+--------------------+-----------+
| 1 | admin | | d033e22ae348aeb5660fc2140aec35850c4da997 | admin@example.com | 1 |
+----+----------+------+------------------------------------------+--------------------+-----------+
+----+----------+------------------------------------------+--------------------+-----------+
| id | username | password | email | is_active |
+----+----------+------------------------------------------+--------------------+-----------+
| 1 | admin | d033e22ae348aeb5660fc2140aec35850c4da997 | admin@example.com | 1 |
+----+----------+------------------------------------------+--------------------+-----------+

The next part will focus on how to authenticate one of these users
thanks to the Doctrine entity user provider and a couple of lines of
Expand Down Expand Up @@ -743,3 +719,46 @@ fetch the user and their associated roles with a single query::
The ``QueryBuilder::leftJoin()`` method joins and fetches related roles from
the ``AcmeUserBundle:User`` model class when a user is retrieved by their email
address or username.

.. _`cookbook-security-serialize-equatable`:

Understanding serialize and how a User is Saved in the Session
--------------------------------------------------------------

If you're curious about the importance of the ``serialize`` method inside
Copy link
Member

Choose a reason for hiding this comment

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

serialize()

the User class or how the User object is serialized or deserialized, then
Copy link
Member

Choose a reason for hiding this comment

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

User should be placed in a literal imo

this section is for you. If not, feel free to skip this.

Once the user is logged in, the entire User object is serialized into the
session. On the next request, the User object is deserialized. Then, value
of the ``id`` property is used to re-query for a fresh User object from the
database. Finally, the fresh User object is compared in some way to the deserialized
User object to make sure that they represent the same user. For example, if
the ``username`` on the 2 User objects doesn't match for some reason, then
the user will be logged out for security reasons.

Even though this all happens automatically, there are a few important side-effects.

First, the :phpclass:`Serializable` interface and its ``serialize`` and ``unserialize``
methods have been added to allow the ``User`` class to be serialized
to the session. This may or may not be needed depending on your setup,
but it's probably a good idea. Only the ``id`` needs to be serialized,
Copy link
Member

Choose a reason for hiding this comment

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

"In the most minimal case, only the id needs to be serialized, ..."

As a native, you properbly can improve this proposal, but we need to make it clear that you should serialze more in the most cases imo

because the :method:`Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider::refreshUser`
method refreshes the user on each request by using the ``id`` (as explained
above). In practice, this means that the User object is reloaded from the
database on each request using the ``id`` from the serialized object. This
makes sure all of the User's data is fresh.


Copy link
Member

Choose a reason for hiding this comment

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

Duplicate new line

Symfony also uses the ``username``, ``salt``, and ``password`` to verify
that the User has not changed between requests. Failing to serialize
these may cause you to be logged out on each request. If your User implements
:class:`Symfony\\Component\\Security\\Core\\User\\EquatableInterface`,
Copy link
Member

Choose a reason for hiding this comment

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

implements the EquatableInterface, ...

then instead of these properties being checked, your ``isEqualTo`` method
is simply called, and you can check whatever properties you want. Unless
you understand this, you probably *won't* need to implement this interface
or worry about it.

.. versionadded:: 2.1
In Symfony 2.1, the ``equals`` method was removed from ``UserInterface``
and the ``EquatableInterface`` was added in its place.
0