8000 Merge pull request #1604 from matthiasnoback/security_component_docum… · pilot/symfony-docs@fc7b8a6 · GitHub
[go: up one dir, main page]

Skip to content

Commit fc7b8a6

Browse files
committed
Merge pull request symfony#1604 from matthiasnoback/security_component_documentation
[Security] [WIP] Add documentation for the Security Component
2 parents 46ca631 + 39be566 commit fc7b8a6

File tree

7 files changed

+616
-0
lines changed

7 files changed

+616
-0
lines changed

components/index.rst

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

components/map.rst.inc

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

6666
* :doc:`/components/serializer`
6767

68+
* :doc:`/components/security/index`
69+
70+
* :doc:`/components/security/introduction`
71+
* :doc:`/components/security/firewall`
72+
* :doc:`/components/security/authentication`
73+
* :doc:`/components/security/authorization`
74+
6875
* **Templating**
6976

7077
* :doc:`/components/templating`
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
.. index::
2+
single: Security, Authentication Manager
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 when 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\AuthenticationProviderInt 9E7A erface
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`. This method
105+
should return an authenticated token or throw an :class:`Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException`
106+
(or any other exception extending it).
107+
108+
Authenticating users by their username and password
109+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110+
111+
An authentication provider will attempt to authenticate a user based on
112+
the credentials he provided. Usually these are a username and a password.
113+
Most web applications store their user's username and a hash of the user's
114+
password combined with a randomly generated salt. This means that the average
115+
authentication would consist of fetching the salt and the hashed password
116+
from the user data storage, hash the password the user has just provided
117+
(e.g. using a login form) with the salt and compare both to determine if
118+
the given password is valid.
119+
120+
This functionality is offered by the :class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\DaoAuthenticationProvider`.
121+
It fetches the user's data from a :class:`Symfony\\Component\\Security\\Core\\User\\UserProviderInterface``,
122+
uses a :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`
123+
to create a hash of the password and returns an authenticated token if the
124+
password was valid::
125+
126+
use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
127+
use Symfony\Component\Security\Core\User\UserChecker;
128+
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
129+
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
130+
131+
$userProvider = new InMemoryUserProvider(
132+
array('admin' => array(
133+
// password is "foo"
134+
'password' => '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg==',
135+
'roles' => array('ROLE_ADMIN'),
136+
),
137+
);
138+
139+
// for some extra checks: is account enabled, locked, expired, etc.?
140+
$userChecker = new UserChecker();
141+
142+
// an array of password encoders (see below)
143+
$encoderFactory = new EncoderFactory(...);
144+
145+
$provider = new DaoAuthenticationProvider(
146+
$userProvider,
147+
$userChecker,
148+
'secured_area',
149+
$encoderFactory
150+
);
151+
152+
$provider->authenticate($unauthenticatedToken);
153+
154+
.. note::
155+
156+
The example above demonstrates the use of the "in-memory" user provider,
157+
but you may use any user provider, as long as it implements
158+
:class:`Symfony\\Component\\Security\\Core\\User\\UserProviderInterface`.
159+
It is also possible to let multiple user providers try to find the user's
160+
data, using the :class:`Symfony\\Component\\Security\\Core\\User\\ChainUserProvider`.
161+
162+
The password encoder factory
163+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164+
165+
The :class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\DaoAuthenticationProvider`
166+
uses an encoder factory to create a password encoder for a given type of
167+
user. This allows you to use different encoding strategies for different
168+
types of users. The default :class:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactory`
169+
receives an array of encoders::
170+
171+
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
172+
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
173+
174+
$defaultEncoder = new MessageDigestPasswordEncoder('sha512', true, 5000);
175+
$weakEncoder = new MessageDigestPasswordEncoder('md5', true, 1);
176+
177+
$encoders = array(
178+
'Symfony\\Component\\Security\\Core\\User\\User' => $defaultEncoder,
179+
'Acme\\Entity\\LegacyUser' => $weakEncoder,
180+
...,
181+
);
182+
183+
$encoderFactory = new EncoderFactory($encoders);
184+
185+
Each encoder should implement :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`
186+
or be an array with a ``class`` and an ``arguments`` key, which allows the
187+
encoder factory to construct the encoder only when it is needed.
188+
189+
Password encoders
190+
~~~~~~~~~~~~~~~~~
191+
192+
When the :method:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactory::getEncoder`
193+
method of the password encoder factory is called with the user object as
194+
its first argument, it will return an encoder of type :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`
195+
which should be used to encode this user's password::
196+
197+
// fetch a user of type Acme\Entity\LegacyUser
198+
$user = ...
199+
200+
$encoder = $encoderFactory->getEncoder($user);
201+
202+
// will return $weakEncoder (see above)
203+
204+
$encodedPassword = $encoder->encodePassword($password, $user->getSalt());
205+
206+
// check if the password is valid:
207+
208+
$validPassword = $encoder->isPasswordValid(
209+
$user->getPassword(),
210+
$password,
211+
$user->getSalt());

0 commit comments

Comments
 (0)
0