Skip to content

Commit 0e3560a

Browse files
Added rough version of Security Component Documentation,
about firewall, firewall map, firewall listeners, authentication manager, password encoder factory, password encoders, user providers
1 parent 114ce6d commit 0e3560a

File tree

6 files changed

+355
-0
lines changed

6 files changed

+355
-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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565

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

68+
* **Security**
69+
70+
* :doc:`/components/security/index`
71+
6872
* **Templating**
6973

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

components/security/firewall.rst

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
.. index::
2+
single: Security, Firewall
3+
4+
The Security Context
5+
====================
6+
7+
Central to the Security Component is the security context, which is an instance
8+
of :class:`Symfony\\Component\\Security\\Core\\SecurityContext`. When all
9+
steps in the process of authenticating the user have been taken successfully,
10+
the security context may be asked if the authenticated user has access
11+
to a certain action or resource of the application.
12+
13+
.. code-block:: php
14+
15+
use Symfony\Component\Security\SecurityContext;
16+
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
17+
18+
$context = new SecurityContext();
19+
20+
// authenticate the user...
21+
22+
if (!$context->isGranted('ROLE_ADMIN')) {
23+
throw new AccessDeniedException();
24+
}
25+
26+
A firewall for HTTP requests
27+
============================
28+
29+
Authenticating a user is done by the firewall. An application may have
30+
multiple secured areas, so the firewall is configured using a map of these
31+
secured areas. For each of these areas, the map contains a request matcher
32+
and a collection of listeners. The request matcher gives the firewall the
33+
ability to find out if the current request points to a secured area.
34+
The listeners are then asked if the current request can be used to authenticate
35+
the user.
36+
37+
.. code-block:: php
38+
39+
use Symfony\Component\Security\Http\FirewallMap;
40+
use Symfony\Component\HttpFoundation\RequestMatcher;
41+
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
42+
43+
$map = new FirewallMap();
44+
45+
$requestMatcher = new RequestMatcher('^/secured-area/');
46+
47+
$listeners = array(
48+
// ...
49+
);
50+
$exceptionListener = new ExceptionListener(/* ... */);
51+
52+
$map->add($requestMatcher, $listeners, $exceptionListener);
53+
54+
The firewall map will be given to the firewall as it's first argument, together
55+
with the event dispatcher that is used by the :class:`Symfony\\Component\\HttpKernel\\HttpKernel`.
56+
57+
.. code-block:: php
58+
59+
use Symfony\Component\Security\Http\Firewall;
60+
use Symfony\Component\HttpKernel\KernelEvents;
61+
62+
// $dispatcher is the EventDispatcher used by the HttpKernel
63+
64+
$firewall = new Firewall($map, $dispatcher);
65+
66+
$dispatcher->register(KernelEvents::REQUEST, array($firewall, 'onKernelRequest');
67+
68+
The firewall is registered to listen to the ``kernel.request`` event that
69+
will be dispatched by the ``HttpKernel`` at the beginning of each request
70+
it processes. This way, the firewall may prevent the user from going any
71+
further than allowed.
72+
73+
Firewall listeners
74+
------------------
75+
76+
When the firewall gets notified of the ``kernel.request`` event, it asks
77+
the firewall map if the request matches any of the secured areas. If it
78+
does, the corresponding listeners (who each implement
79+
:class:`Symfony\\Component\\Security\\Http\\Firewall\\ListenerInterface`)
80+
will be asked to handle the current request. This basically means: find
81+
out if the current request contains any information by which the user might
82+
be authenticated (for instance the Basic HTTP authentication listener checks
83+
if the request has a header called "PHP_AUTH_USER").
84+
85+
Exception listener
86+
------------------
87+
88+
If any of the listeners throws an :class:`Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException`
89+
(or any exception extending this exception), the exception listener that
90+
was provided when adding secured areas to the firewall map will jump in.
91+
92+
The exception listener determines what happens next, based on the arguments
93+
it received when it was created. It may start the authentication procedure,
94+
maybe ask the user to supply his credentials again (when he has only been
95+
authenticated based on a "remember-me" cookie), or transform the exception
96+
into an :class:`Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException`,
97+
which will eventually result in an "HTTP/1.1 401: Access Denied" response.
98+
99+
Entry points
100+
------------
101+
102+
When the user is not authenticated at all (i.e. when the security context
103+
has no token yet), the firewall's entry point will be called to "start"
104+
the authentication process. An entry point should implement
105+
:class:`Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface`,
106+
which has only one method: ``start()``. This method receives the
107+
current :class:`Symfony\\Component\\HttpFoundation\\Request` object and
108+
the exception by which the exception listener was triggered. The method
109+
should return a :class:`Symfony\\Component\\HttpFoundation\\Response` object,
110+
for instance the page containing the login form, or in the case of Basic
111+
HTTP authentication a response with a "WWW-Authenticate" header, which will
112+
prompt the user to supply his username and password.

components/security/index.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Security
2+
========
3+
4+
.. toctree::
5+
:maxdepth: 2
6+
7+
introduction
8+
firewall
9+
authentication
10+
authorization

components/security/introduction.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.. index::
2+
single: Security
3+
4+
The Security Component
5+
======================
6+
7+
Introduction
8+
------------
9+
10+
The Security Component provides a complete security system for your web
11+
application. It ships with facilities for authenticating using HTTP basic
12+
or digest authentication, interactive form login or X.509 certificate login,
13+
but also allows you to implement your own authentication strategies.
14+
Furthermore, the component provides ways to authorize authenticated users
15+
based on their roles, and it contains an advanced ACL system.
16+
17+
Installation
18+
------------
19+
20+
You can install the component in many different ways:
21+
22+
* Use the official Git repository (https://github.com/symfony/Security);
23+
* Install it via PEAR ( `pear.symfony.com/Security`);
24+
* Install it via Composer (`symfony/security` on Packagist).
25+
26+
Sections
27+
--------
28+
29+
* :doc:`/components/security/firewall`
30+
* :doc:`/components/security/authentication`

0 commit comments

Comments
 (0)