Skip to content

[Security] renamed memory provider and a tip about encoder for all user types #13146

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 1 commit into from
Feb 16, 2020
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
117 changes: 98 additions & 19 deletions security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ configuration looks like this:
# app/config/security.yml
security:
providers:
in_memory:
users_in_memory:
memory: ~

firewalls:
Expand All @@ -55,6 +55,7 @@ configuration looks like this:

main:
anonymous: ~
provider: users_in_memory

.. code-block:: xml

Expand All @@ -67,7 +68,7 @@ configuration looks like this:
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<provider name="in_memory">
<provider name="users_in_memory">
<memory/>
</provider>

Expand All @@ -77,6 +78,7 @@ configuration looks like this:

<firewall name="main">
<anonymous/>
<provider>users_in_memory</provider>
</firewall>
</config>
</srv:container>
Expand All @@ -86,7 +88,7 @@ configuration looks like this:
// app/config/security.php
$container->loadFromExtension('security', [
'providers' => [
'in_memory' => [
'users_in_memory' => [
'memory' => null,
],
],
Expand All @@ -97,6 +99,7 @@ configuration looks like this:
],
'main' => [
'anonymous' => null,
'provider' => 'users_in_memory'
],
],
]);
Expand Down Expand Up @@ -315,7 +318,7 @@ provider, but it's better to think of it as an "in configuration" provider:
# app/config/security.yml
security:
providers:
in_memory:
users_in_memory:
memory:
users:
ryan:
Expand All @@ -324,7 +327,11 @@ provider, but it's better to think of it as an "in configuration" provider:
admin:
password: kitten
roles: 'ROLE_ADMIN'
# ...

firewalls:
main:
provider: users_in_memory
# ...

.. code-block:: xml

Expand All @@ -337,13 +344,16 @@ provider, but it's better to think of it as an "in configuration" provider:
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<provider name="in_memory">
<provider name="users_in_memory">
<memory>
<user name="ryan" password="ryanpass" roles="ROLE_USER"/>
<user name="admin" password="kitten" roles="ROLE_ADMIN"/>
</memory>
</provider>
<!-- ... -->
<firewall name="main">
<provider>users_in_memory</provider>
<!-- ... -->
</firewall>
</config>
</srv:container>

Expand All @@ -352,7 +362,7 @@ provider, but it's better to think of it as an "in configuration" provider:
// app/config/security.php
$container->loadFromExtension('security', [
'providers' => [
'in_memory' => [
'users_in_memory' => [
'memory' => [
'users' => [
'ryan' => [
Expand All @@ -367,13 +377,17 @@ provider, but it's better to think of it as an "in configuration" provider:
],
],
],
// ...
'firewalls' => [
'main' => [
'provider' => 'users_in_memory',
],
],
]);

Like with ``firewalls``, you can have multiple ``providers``, but you'll
probably only need one. If you *do* have multiple, you can configure which
probably only need one. If you *do* have multiple, you have to configure which
*one* provider to use for your firewall under its ``provider`` key (e.g.
``provider: in_memory``).
``provider: users_in_memory``).

.. seealso::

Expand Down Expand Up @@ -421,20 +435,22 @@ To fix this, add an ``encoders`` key:
.. code-block:: php

// app/config/security.php
use Symfony\Component\Security\Core\User\User;

$container->loadFromExtension('security', [
// ...

'encoders' => [
'Symfony\Component\Security\Core\User\User' => 'plaintext',
User::class => 'plaintext',
],
// ...
]);

User providers load user information and put it into a ``User`` object. If
you :doc:`load users from the database </security/entity_provider>`
User providers load user information and put it into a :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface`
implementation. If you :doc:`load users from the database </security/entity_provider>`
or :doc:`some other source </security/custom_provider>`, you'll
use your own custom User class. But when you use the "in memory" provider,
it gives you a ``Symfony\Component\Security\Core\User\User`` object.
use your own custom User class. But when you use the "in memory" provider type,
it gives you a :class:`Symfony\\Component\\Security\\Core\\User\\User` object.

Whatever your User class is, you need to tell Symfony what algorithm was
used to encode the passwords. In this case, the passwords are just plaintext,
Expand All @@ -449,6 +465,67 @@ you who you are and what roles you have:
Because this URL requires ``ROLE_ADMIN``, if you had logged in as ``ryan``,
this would deny you access. More on that later (:ref:`security-authorization-access-control`).

.. tip::

If you have many providers and want to define the same encoder for all of
them, you can configure as follow:

.. configuration-block::

.. code-block:: yaml

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

# is equivalent to:
AppBundle\Entity\User: bcrypt
Symfony\Component\Security\Core\User\User: bcrypt
# and any other type you may add in the future
# ...

.. 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
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<encoder class="Symfony\Component\Security\Core\User\UserInterface"
algorithm="bcrypt"/>
<!-- is equivalent to: -->
<encoder class="AppBundle\Entity\User"
algorithm="bcrypt"/>
<encoder class="Symfony\Component\Security\Core\User\User"
algorithm="bcrypt"/>
<!-- and any other type you may add in the future -->

<!-- ... -->
</config>
</srv:container>

.. code-block:: php

// app/config/security.php
use Symfony\Component\Security\Core\User\UserInterface;

$container->loadFromExtension('security', [
'encoders' => [
UserInterface::class => 'bcrypt',

// is equivalent to:
AppBundle\Entity\User::class => 'bcrypt',
Symfony\Component\Security\Core\User\User::class => 'bcrypt',
// and any other type you may add in the future
],
// ...
]);

Loading Users from the Database
...............................

Expand Down Expand Up @@ -502,11 +579,13 @@ is ``bcrypt``:
.. code-block:: php

// app/config/security.php
use Symfony\Component\Security\Core\User\User;

$container->loadFromExtension('security', [
// ...

'encoders' => [
'Symfony\Component\Security\Core\User\User' => [
User::class => [
'algorithm' => 'bcrypt',
'cost' => 12,
]
Expand All @@ -532,7 +611,7 @@ It will give you something like this:
# ...

providers:
in_memory:
users_in_memory:
memory:
users:
ryan:
Expand Down Expand Up @@ -571,7 +650,7 @@ It will give you something like this:
// ...

'providers' => [
'in_memory' => [
'users_in_memory' => [
'memory' => [
'users' => [
'ryan' => [
Expand Down
48 changes: 24 additions & 24 deletions security/multiple_user_providers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ a new provider that chains the two together:
# app/config/security.yml
security:
providers:
chain_provider:
users:
chain:
providers: [in_memory, user_db]
in_memory:
providers: [users_in_memory, users_in_db]
users_in_memory:
memory:
users:
foo: { password: test }
user_db:
users_in_db:
entity: { class: AppBundle\Entity\User, property: username }

.. code-block:: xml
Expand All @@ -41,20 +41,20 @@ a new provider that chains the two together:
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<provider name="chain_provider">
<provider name="users">
<chain>
<provider>in_memory</provider>
<provider>user_db</provider>
<provider>users_in_memory</provider>
<provider>users_in_db</provider>
</chain>
</provider>

<provider name="in_memory">
<provider name="users_in_memory">
<memory>
<user name="foo" password="test"/>
</memory>
</provider>

<provider name="user_db">
<provider name="users_in_db">
<entity class="AppBundle\Entity\User" property="username"/>
</provider>
</config>
Expand All @@ -67,19 +67,19 @@ a new provider that chains the two together:

$container->loadFromExtension('security', [
'providers' => [
'chain_provider' => [
'users' => [
'chain' => [
'providers' => ['in_memory', 'user_db'],
],
],
'in_memory' => [
'users_in_memory' => [
'memory' => [
'users' => [
'foo' => ['password' => 'test'],
],
],
],
'user_db' => [
'users_in_db' => [
'entity' => [
'class' => User::class,
'property' => 'username',
Expand All @@ -88,14 +88,14 @@ a new provider that chains the two together:
],
]);

Now, all firewalls that explicitly define ``chain_provider`` as their user
provider will, in turn, try to load the user from both the ``in_memory`` and
``user_db`` providers.
Now, all firewalls that explicitly define ``users`` as their user
provider will, in turn, try to load the user from both the ``users_in_memory`` then
``users_in_db`` providers.

.. deprecated:: 3.4

In previous Symfony versions, firewalls that didn't define their user provider
explicitly, used the first existing provider (``chain_provider`` in this
explicitly, used the first existing provider (``users`` in this
example). However, auto-selecting the first user provider has been deprecated
in Symfony 3.4 and will throw an exception in 4.0. Always define the provider
used by the firewall when there are multiple providers.
Expand All @@ -114,10 +114,10 @@ the first provider is always used:
secured_area:
# ...
pattern: ^/
provider: user_db
provider: users_in_db
http_basic:
realm: 'Secured Demo Area'
provider: in_memory
provider: users_in_memory
form_login: ~

.. code-block:: xml
Expand All @@ -131,9 +131,9 @@ the first provider is always used:
https://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<firewall name="secured_area" pattern="^/" provider="user_db">
<firewall name="secured_area" pattern="^/" provider="users_in_db">
<!-- ... -->
<http-basic realm="Secured Demo Area" provider="in_memory"/>
<http-basic realm="Secured Demo Area" provider="users_in_memory"/>
<form-login/>
</firewall>
</config>
Expand All @@ -147,20 +147,20 @@ the first provider is always used:
'secured_area' => [
// ...
'pattern' => '^/',
'provider' => 'user_db',
'provider' => 'users_in_db',
'http_basic' => [
// ...
'realm' => 'Secured Demo Area',
'provider' => 'in_memory',
'provider' => 'users_in_memory',
],
'form_login' => [],
],
],
]);

In this example, if a user tries to log in via HTTP authentication, the authentication
system will use the ``in_memory`` user provider. But if the user tries to
log in via the form login, the ``user_db`` provider will be used (since it's
system will use the ``users_in_memory`` user provider. But if the user tries to
log in via the form login, the ``users_in_db`` provider will be used (since it's
the default for the firewall as a whole).

If you need to check that the user being returned by your provider is a allowed
Expand Down