Skip to content

Commit 6c9dc44

Browse files
committed
Merge branch '2.0' into 2.1
Conflicts: cookbook/form/form_collections.rst
2 parents 6cf091d + e5360fb commit 6c9dc44

File tree

9 files changed

+636
-3
lines changed

9 files changed

+636
-3
lines changed

components/http_foundation/introduction.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ argument::
167167

168168
.. _component-foundation-attributes:
169169

170-
Last, but not the least, you can also store additional data in the request,
171-
thanks to the ``attributes`` public property, which is also an instance of
170+
Finally, you can also store additional data in the request,
171+
thanks to the public ``attributes`` property, which is also an instance of
172172
:class:`Symfony\\Component\\HttpFoundation\\ParameterBag`. This is mostly used
173173
to attach information that belongs to the Request and that needs to be
174174
accessed from many different points in your application. For information

components/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The Components
1818
locale
1919
process
2020
routing/index
21+
security/index
2122
serializer
2223
templating
2324
yaml

components/map.rst.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@
7474

7575
* :doc:`/components/serializer`
7676

77+
* :doc:`/components/security/index`
78+
79+
* :doc:`/components/security/introduction`
80+
* :doc:`/components/security/firewall`
81+
* :doc:`/components/security/authentication`
82+
* :doc:`/components/security/authorization`
83+
7784
* **Templating**
7885

7986
* :doc:`/components/templating`
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
.. index::
2+
single: Security, Authentication
3+
4+
Authentication
5+
==============
6+
7+
When a request points to a secured area, and one of the listeners from the
8+
firewall map is able to extract the user's credentials from the current
9+
:class:`Symfony\\Component\\HttpFoundation\\Request` object, it should create
10+
a token, containing these credentials. The next thing the listener should
11+
do is ask the authentication manager to validate the given token, and return
12+
an *authenticated* token if the supplied credentials were found to be valid.
13+
The listener should then store the authenticated token in the security context::
14+
15+
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
16+
use Symfony\Component\Security\Core\SecurityContextInterface;
17+
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
18+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
19+
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
20+
21+
class SomeAuthenticationListener implements ListenerInterface
22+
{
23+
/**
24+
* @var SecurityContextInterface
25+
*/
26+
private $securityContext;
27+
28+
/**
29+
* @var AuthenticationManagerInterface
30+
*/
31+
private $authenticationManager;
32+
33+
/**
34+
* @var string Uniquely identifies the secured area
35+
*/
36+
private $providerKey;
37+
38+
// ...
39+
40+
public function handle(GetResponseEvent $event)
41+
{
42+
$request = $event->getRequest();
43+
44+
$username = ...;
45+
$password = ...;
46+
47+
$unauthenticatedToken = new UsernamePasswordToken(
48+
$username,
49+
$password,
50+
$this->providerKey
51+
);
52+
53+
$authenticatedToken = $this
54+
->authenticationManager
55+
->authenticate($unauthenticatedToken);
56+
57+
$this->securityContext->setToken($authenticatedToken);
58+
}
59+
}
60+
61+
.. note::
62+
63+
A token can be of any class, as long as it implements
64+
:class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface`.
65+
66+
The Authentication Manager
67+
--------------------------
68+
69+
The default authentication manager is an instance of
70+
:class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationProviderManager`::
71+
72+
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
73+
74+
// instances of Symfony\Component\Security\Core\Authentication\AuthenticationProviderInterface
75+
$providers = array(...);
76+
77+
$authenticationManager = new AuthenticationProviderManager($providers);
78+
79+
try {
80+
$authenticatedToken = $authenticationManager
81+
->authenticate($unauthenticatedToken);
82+
} catch (AuthenticationException $failed) {
83+
// authentication failed
84+
}
85+
86+
The ``AuthenticationProviderManager``, when instantiated, receives several
87+
authentication providers, each supporting a different type of token.
88+
89+
.. note::
90+
91+
You may of course write your own authentication manager, it only has
92+
to implement :class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationManagerInterface`.
93+
94+
.. _authentication_providers:
95+
96+
Authentication providers
97+
------------------------
98+
99+
Each provider (since it implements
100+
:class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\AuthenticationProviderInterface`)
101+
has a method :method:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\AuthenticationProviderInterface::supports`
102+
by which the ``AuthenticationProviderManager``
103+
can determine if it supports the given token. If this is the case, the
104+
manager then calls the provider's method :class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\AuthenticationProviderInterface::authenticate`.
105+
This method should return an authenticated token or throw an
106+
:class:`Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException`
107+
(or any other exception extending it).
108+
109+
Authenticating Users by their Username and Password
110+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111+
112+
An authentication provider will attempt to authenticate a user based on
113+
the credentials he provided. Usually these are a username and a password.
114+
Most web applications store their user's username and a hash of the user's
115+
password combined with a randomly generated salt. This means that the average
116+
authentication would consist of fetching the salt and the hashed password
117+
from the user data storage, hash the password the user has just provided
118+
(e.g. using a login form) with the salt and compare both to determine if
119+
the given password is valid.
120+
121+
This functionality is offered by the :class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\DaoAuthenticationProvider`.
122+
It fetches the user's data from a :class:`Symfony\\Component\\Security\\Core\\User\\UserProviderInterface``,
123+
uses a :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`
124+
to create a hash of the password and returns an authenticated token if the
125+
password was valid::
126+
127+
use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
128+
use Symfony\Component\Security\Core\User\UserChecker;
129+
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
130+
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
131+
132+
$userProvider = new InMemoryUserProvider(
133+
array('admin' => array(
134+
// password is "foo"
135+
'password' => '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg==',
136+
'roles' => array('ROLE_ADMIN'),
137+
),
138+
);
139+
140+
// for some extra checks: is account enabled, locked, expired, etc.?
141+
$userChecker = new UserChecker();
142+
143+
// an array of password encoders (see below)
144+
$encoderFactory = new EncoderFactory(...);
145+
146+
$provider = new DaoAuthenticationProvider(
147+
$userProvider,
148+
$userChecker,
149+
'secured_area',
150+
$encoderFactory
151+
);
152+
153+
$provider->authenticate($unauthenticatedToken);
154+
155+
.. note::
156+
157+
The example above demonstrates the use of the "in-memory" user provider,
158+
but you may use any user provider, as long as it implements
159+
:class:`Symfony\\Component\\Security\\Core\\User\\UserProviderInterface`.
160+
It is also possible to let multiple user providers try to find the user's
161+
data, using the :class:`Symfony\\Component\\Security\\Core\\User\\ChainUserProvider`.
162+
163+
The Password encoder Factory
164+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165+
166+
The :class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\DaoAuthenticationProvider`
167+
uses an encoder factory to create a password encoder for a given type of
168+
user. This allows you to use different encoding strategies for different
169+
types of users. The default :class:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactory`
170+
receives an array of encoders::
171+
172+
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
173+
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
174+
175+
$defaultEncoder = new MessageDigestPasswordEncoder('sha512', true, 5000);
176+
$weakEncoder = new MessageDigestPasswordEncoder('md5', true, 1);
177+
178+
$encoders = array(
179+
'Symfony\\Component\\Security\\Core\\User\\User' => $defaultEncoder,
180+
'Acme\\Entity\\LegacyUser' => $weakEncoder,
181+
...,
182+
);
183+
184+
$encoderFactory = new EncoderFactory($encoders);
185+
186+
Each encoder should implement :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`
187+
or be an array with a ``class`` and an ``arguments`` key, which allows the
188+
encoder factory to construct the encoder only when it is needed.
189+
190+
Password Encoders
191+
~~~~~~~~~~~~~~~~~
192+
193+
When the :method:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactory::getEncoder`
194+
method of the password encoder factory is called with the user object as
195+
its first argument, it will return an encoder of type :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`
196+
which should be used to encode this user's password::
197+
198+
// fetch a user of type Acme\Entity\LegacyUser
199+
$user = ...
200+
201+
$encoder = $encoderFactory->getEncoder($user);
202+
203+
// will return $weakEncoder (see above)
204+
205+
$encodedPassword = $encoder->encodePassword($password, $user->getSalt());
206+
207+
// check if the password is valid:
208+
209+
$validPassword = $encoder->isPasswordValid(
210+
$user->getPassword(),
211+
$password,
212+
$user->getSalt());

0 commit comments

Comments
 (0)