Skip to content
Newer
Older
100644 1662 lines (1258 sloc) 58.5 KB
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1 Security
2 ========
3
4 Security is a two-step process whose goal is to prevent a user from accessing
5 a resource that he/she should not have access to.
6
7 In the first step of the process, the security system identifies who the user
8 is by requiring the user to submit some sort of identification. This is called
9 **authentication**, and it means that the system is trying to find out who
10 you are.
11
12 Once the system knows who you are, the next step is to determine if you should
13 have access to a given resource. This part of the process is called **authorization**,
14 and it means that the system is checking to see if you have privileges to
15 perform a certain action.
16
6688eb3 @weaverryan [book][security] Fixing formatting
weaverryan authored May 16, 2011
17 .. image:: /images/book/security_authentication_authorization.png
18 :align: center
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
19
20 Since the best way to learn is to see an example, let's dive right in.
21
22 .. note::
23
24 Symfony's `security component`_ is available as a standalone PHP library
25 for use inside any PHP project.
26
27 Basic Example: HTTP Authentication
28 ----------------------------------
29
30 The security component can be configured via your application configuration.
31 In fact, most standard security setups are just matter of using the right
32 configuration. The following configuration tells Symfony to secure any URL
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 12, 2011
33 matching ``/admin/*`` and to ask the user for credentials using basic HTTP
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
34 authentication (i.e. the old-school username/password box):
35
36 .. configuration-block::
37
38 .. code-block:: yaml
39
40 # app/config/config.yml
41 security:
42 firewalls:
43 secured_area:
44 pattern: ^/
45 anonymous: ~
46 http_basic:
47 realm: "Secured Demo Area"
48
49 access_control:
50 - { path: ^/admin, roles: ROLE_ADMIN }
51
52 providers:
53 in_memory:
54 users:
55 ryan: { password: ryanpass, roles: 'ROLE_USER' }
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
56 admin: { password: kitten, roles: 'ROLE_ADMIN' }
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
57
58 encoders:
59 Symfony\Component\Security\Core\User\User: plaintext
60
61 .. code-block:: xml
62
63 <!-- app/config/config.xml -->
64 <srv:container xmlns="http://symfony.com/schema/dic/security"
65 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
66 xmlns:srv="http://symfony.com/schema/dic/services"
67 xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
68
69 <config>
70 <firewall name="secured_area" pattern="^/">
71 <anonymous />
72 <http-basic realm="Secured Demo Area" />
73 </firewall>
74
75 <access-control>
76 <rule path="^/admin" role="ROLE_ADMIN" />
77 </access-control>
78
79 <provider name="in_memory">
80 <user name="ryan" password="ryanpass" roles="ROLE_USER" />
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
81 <user name="admin" password="kitten" roles="ROLE_ADMIN" />
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
82 </provider>
83
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
84 <encoder class="Symfony\Component\Security\Core\User\User" algorithm="plaintext" />
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
85 </config>
86 </srv:container>
87
88 .. code-block:: php
89
90 // app/config/config.php
91 $container->loadFromExtension('security', array(
92 'firewalls' => array(
93 'secured_area' => array(
94 'pattern' => '^/',
95 'anonymous' => array(),
96 'http_basic' => array(
97 'realm' => 'Secured Demo Area',
98 ),
99 ),
100 ),
101 'access_control' => array(
102 array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
103 ),
104 'providers' => array(
105 'in_memory' => array(
106 'users' => array(
107 'ryan' => array('password' => 'ryanpass', 'roles' => 'ROLE_USER'),
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
108 'admin' => array('password' => 'kitten', 'roles' => 'ROLE_ADMIN'),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
109 ),
110 ),
111 ),
112 'encoders' => array(
113 'Symfony\Component\Security\Core\User\User' => 'plaintext',
114 ),
115 ));
116
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 11, 2011
117 .. tip::
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
118
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
119 A standard Symfony distribution separates the security configuration
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
120 into a separate file (e.g. ``app/config/security.yml``). If you don't
121 have a separate security file, you can put the configuration directly
122 into your main config file (e.g. ``app/config/config.yml``).
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
123
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
124 The end result of this configuration is a fully-functional security system
125 that looks like the following:
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
126
4ed0f96 @weaverryan [book][security] Fixing improper bullet spacing
weaverryan authored May 14, 2011
127 * There are two users in the system (``ryan`` and ``admin``);
128 * Users authenticate themselves via the basic HTTP authentication prompt;
129 * Any URL matching ``/admin/*`` is secured, and only the ``admin`` user
130 can access it;
131 * All URLs *not* matching ``/admin/*`` are accessible by all users (and the
132 user is never prompted to login).
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
133
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
134 Let's look briefly at how security works and how each part of the configuration
135 comes into play.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
136
137 How Security Works: Authentication and Authorization
138 ----------------------------------------------------
139
140 Symfony's security system works by determining who a user is (i.e. authentication)
141 and then checking to see if that user should have access to a specific resource
142 or URL.
143
144 Firewalls (Authentication)
145 ~~~~~~~~~~~~~~~~~~~~~~~~~~
146
147 When a user makes a request to a URL that's protected by a firewall, the
148 security system is activated. The job of the firewall is to determine whether
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
149 or not the user needs to be authenticated, and if he does, to send a response
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
150 back to the user initiating the authentication process.
151
152 A firewall is activated when the URL of an incoming request matches the configured
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
153 firewall's regular expression ``pattern`` config value. In this example, the
154 ``pattern`` (``^/``) will match *every* incoming request. The fact that the
155 firewall is activated does *not* mean, however, that the HTTP authentication
156 username and password box is displayed for every URL. For example, any user
157 can access ``/foo`` without being prompted to authenticate.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
158
f3031ad @weaverryan [book][security] Adding in the image files and re-working some language
weaverryan authored May 12, 2011
159 .. image:: /images/book/security_anonymous_user_access.png
160 :align: center
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
161
162 This works first because the firewall allows *anonymous users* via the ``anonymous``
163 configuration parameter. In other words, the firewall doesn't require the
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
164 user to fully authenticate immediately. And because no special ``role`` is
165 needed to access ``/foo`` (under the ``access_control`` section), the request
166 can be fulfilled without ever asking the user to authenticate.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
167
168 If you remove the ``anonymous`` key, the firewall will *always* make a user
169 fully authenticate immediately.
170
171 Access Controls (Authorization)
172 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173
174 If a user requests ``/admin/foo``, however, the process behaves differently.
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
175 This is because of the ``access_control`` configuration section that says
65c5e15 @weaverryan [book][security] Fixing two errors per @stof
weaverryan authored May 16, 2011
176 that any URL matching the regular expression pattern ``^/admin`` (i.e. ``/admin``
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
177 or anything matching ``/admin/*``) requires the ``ROLE_ADMIN`` role. Roles
178 are the basis for most authorization: a user can access ``/admin/foo`` only
179 if it has the ``ROLE_ADMIN`` role.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
180
f3031ad @weaverryan [book][security] Adding in the image files and re-working some language
weaverryan authored May 12, 2011
181 .. image:: /images/book/security_anonymous_user_denied_authorization.png
182 :align: center
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
183
184 Like before, when the user originally makes the request, the firewall doesn't
185 ask for any identification. However, as soon as the access control layer
186 denies the user access (because the anonymous user doesn't have the ``ROLE_ADMIN``
f3031ad @weaverryan [book][security] Adding in the image files and re-working some language
weaverryan authored May 12, 2011
187 role), the firewall jumps into action and initiates the authentication process.
188 The authentication process depends on the authentication mechanism you're
189 using. For example, if you're using the form login authentication method,
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
190 the user will be redirected to the login page. If you're using HTTP authentication,
f3031ad @weaverryan [book][security] Adding in the image files and re-working some language
weaverryan authored May 12, 2011
191 the user will be sent an HTTP 401 response so that the user sees the username
192 and password box.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
193
194 The user now has the opportunity to submit its credentials back to the application.
195 If the credentials are valid, the original request can be re-tried.
196
f3031ad @weaverryan [book][security] Adding in the image files and re-working some language
weaverryan authored May 12, 2011
197 .. image:: /images/book/security_ryan_no_role_admin_access.png
198 :align: center
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
199
200 In this example, the user ``ryan`` successfully authenticates with the firewall.
201 But since ``ryan`` doesn't have the ``ROLE_ADMIN`` role, he's still denied
202 access to ``/admin/foo``. Ultimately, this means that the user will see some
203 sort of message indicating that access has been denied.
204
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
205 .. tip::
206
207 When Symfony denies the user access, the user sees an error screen and
208 receives a 403 HTTP status code (``Forbidden``). You can customize the
209 access denied error screen by following the directions in the
210 :ref:`Error Pages<cookbook-error-pages-by-status-code>` cookbook entry
211 to customize the 403 error page.
212
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
213 Finally, if the ``admin`` user requests ``/admin/foo``, a similar process
214 takes place, except now, after being authenticated, the access control layer
215 will let the request pass through:
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
216
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
217 .. image:: /images/book/security_admin_role_access.png
218 :align: center
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
219
220 The request flow when a user requests a protected resource is straightforward,
221 but incredibly flexible. As you'll see later, authentication can be handled
222 in any number of ways, including via a form login, X.509 certificate, or by
223 authenticating the user via Twitter. Regardless of the authentication method,
224 the request flow is always the same:
225
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
226 #. A user accesses a protected resource;
227 #. The application redirects the user to the login form;
228 #. The user submits its credentials (e.g. username/password);
229 #. The firewall authenticates the user;
230 #. The authenticated user re-tries the original request.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
231
232 .. note::
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
233
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
234 The *exact* process actually depends a little bit on which authentication
235 mechanism you're using. For example, when using form login, the user
236 submits its credentials to one URL that processes the form (e.g. ``/login_check``)
237 and then is redirected back to the originally requested URL (e.g. ``/admin/foo``).
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
238 But with HTTP authentication, the user submits its credentials directly
239 to the original URL (e.g. ``/admin/foo``) and then the page is returned
240 to the user in that same request (i.e. no redirect).
241
242 These types of idiosyncrasies shouldn't cause you any problems, but they're
243 good to keep in mind.
244
245 .. tip::
246
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
247 You'll also learn later how *anything* can be secured in Symfony2, including
248 specific controllers, objects, or even PHP methods.
249
97dcf3a @weaverryan [security] Filling in more form login config reference
weaverryan authored Jun 18, 2011
250 .. _book-security-form-login:
251
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
252 Using a Traditional Login Form
253 ------------------------------
254
255 So far, you've seen how to blanket your application beneath a firewall and
256 then protect access to certain areas with roles. By using HTTP Authentication,
257 you can effortlessly tap into the native username/password box offered by
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
258 all browsers. However, Symfony supports many authentication mechanisms out
259 of the box. For details on all of them, see the
260 :doc:`Security Configuration Reference</reference/configuration/security>`.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
261
262 In this section, you'll enhance this process by allowing the user to authenticate
263 via a traditional HTML login form.
264
265 First, enable form login under your firewall:
266
267 .. configuration-block::
268
269 .. code-block:: yaml
270
271 # app/config/config.yml
272 security:
273 firewalls:
274 secured_area:
275 pattern: ^/
276 anonymous: ~
277 form_login:
278 login_path: /login
279 check_path: /login_check
280
281 .. code-block:: xml
282
283 <!-- app/config/config.xml -->
284 <srv:container xmlns="http://symfony.com/schema/dic/security"
285 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
286 xmlns:srv="http://symfony.com/schema/dic/services"
287 xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
288
289 <config>
290 <firewall name="secured_area" pattern="^/">
291 <anonymous />
292 <form-login login_path="/login" check_path="/login_check" />
293 </firewall>
294 </config>
295 </srv:container>
296
297 .. code-block:: php
298
299 // app/config/config.php
300 $container->loadFromExtension('security', array(
301 'firewalls' => array(
302 'secured_area' => array(
303 'pattern' => '^/',
304 'anonymous' => array(),
305 'form_login' => array(
306 'login_path' => '/login',
307 'check_path' => '/login_check',
308 ),
309 ),
310 ),
311 ));
312
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
313 .. tip::
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
314
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
315 If you don't need to customize your ``login_path`` or ``check_path``
316 values (the values used here are the default values), you can shorten
317 your configuration:
318
319 .. configuration-block::
320
321 .. code-block:: yaml
322
323 form_login: ~
324
325 .. code-block:: xml
326
327 <form-login />
328
329 .. code-block:: php
330
331 'form_login' => array(),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
332
333 Now, when the security system initiates the authentication process, it will
334 redirect the user to the login form (``/login`` by default). Implementing
335 this login form visually is your job. First, create two routes: one that
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
336 will display the login form (i.e. ``/login``) and one that will handle the
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
337 login form submission (i.e. ``/login_check``):
338
339 .. configuration-block::
340
341 .. code-block:: yaml
342
343 # app/config/routing.yml
344 login:
345 pattern: /login
346 defaults: { _controller: AcmeSecurityBundle:Security:login }
347 login_check:
348 pattern: /login_check
349
350 .. code-block:: xml
351
352 <!-- app/config/routing.xml -->
353 <?xml version="1.0" encoding="UTF-8" ?>
354
355 <routes xmlns="http://symfony.com/schema/routing"
356 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
357 xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
358
359 <route id="login" pattern="/login">
360 <default key="_controller">AcmeSecurityBundle:Security:login</default>
361 </route>
362 <route id="login_check" pattern="/login_check" />
363
364 </routes>
365
366 .. code-block:: php
367
368 // app/config/routing.php
369 use Symfony\Component\Routing\RouteCollection;
370 use Symfony\Component\Routing\Route;
371
372 $collection = new RouteCollection();
373 $collection->add('login', new Route('/login', array(
374 '_controller' => 'AcmeDemoBundle:Security:login',
375 )));
376 $collection->add('login_check', new Route('/login_check', array()));
377
378 return $collection;
379
380 .. note::
381
c4b0e78 @weaverryan [book][security] Tweaking language about why we need a login_check URL
weaverryan authored May 14, 2011
382 You will *not* need to implement a controller for the ``/login_check``
383 URL as the firewall will automatically catch and process any form submitted
384 to this URL. It's optional, but helpful, to create a route so that you
385 can use it to generate the form submission URL in the login template below.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
386
c4b0e78 @weaverryan [book][security] Tweaking language about why we need a login_check URL
weaverryan authored May 14, 2011
387 Notice that the name of the ``login`` route isn't important. What's important
388 is that the URL of the route (``/login``) matches the ``check_path`` config
389 value, as that's where the security system will redirect users that need
390 to login.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
391
392 Next, create the controller that will display the login form:
393
394 .. code-block:: php
395
396 // src/Acme/SecurityBundle/Controller/Main;
397 namespace Acme\SecurityBundle\Controller;
398
399 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
400 use Symfony\Component\Security\Core\SecurityContext;
401
402 class SecurityController extends Controller
403 {
404 public function loginAction()
405 {
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
406 // get the login error if there is one
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
407 if ($this->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
408 $error = $this->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
409 } else {
410 $error = $this->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
411 }
412
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
413 return $this->render('AcmeSecurityBundle:Security:login.html.twig', array(
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
414 // last username entered by the user
415 'last_username' => $this->get('request')->getSession()->get(SecurityContext::LAST_USERNAME),
416 'error' => $error,
417 ));
418 }
419 }
420
421 Don't let this controller confuse you. As you'll see in a moment, when the
422 user submits the form, the security system automatically handles the form
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
423 submission for you. If the user had submitted an invalid username or password,
424 this controller reads the form submission error from the security system so
425 that it can be displayed back to the user.
426
427 In other words, your job is to display the login form and any login errors
428 that may have occurred, but the security system itself takes care of checking
429 the submitted username and password and authenticating the user.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
430
c4b0e78 @weaverryan [book][security] Tweaking language about why we need a login_check URL
weaverryan authored May 14, 2011
431 Finally, create the corresponding template:
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
432
433 .. configuration-block::
434
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
435 .. code-block:: html+jinja
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
436
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
437 {# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #}
438 {% if error %}
439 <div>{{ error.message }}</div>
440 {% endif %}
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
441
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
442 <form action="{{ path('login_check') }}" method="post">
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
443 <label for="username">Username:</label>
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
444 <input type="text" id="username" name="_username" value="{{ last_username }}" />
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
445
446 <label for="password">Password:</label>
447 <input type="password" id="password" name="_password" />
448
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
449 {#
450 If you want to control the URL the user is redirected to on success (more details below)
451 <input type="hidden" name="_target_path" value="/account" />
452 #}
453
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
454 <input type="submit" name="login" />
455 </form>
456
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
457 .. code-block:: html+php
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
458
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
459 <?php // src/Acme/SecurityBundle/Resources/views/Security/login.html.php ?>
460 <?php if ($error): ?>
461 <div><?php echo $error->getMessage() ?></div>
462 <?php endif; ?>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
463
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
464 <form action="<?php echo $view['router']->generate('login_check') ?>" method="post">
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
465 <label for="username">Username:</label>
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
466 <input type="text" id="username" name="_username" value="<?php echo $last_username ?>" />
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
467
468 <label for="password">Password:</label>
469 <input type="password" id="password" name="_password" />
470
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
471 <!--
472 If you want to control the URL the user is redirected to on success (more details below)
473 <input type="hidden" name="_target_path" value="/account" />
474 -->
475
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
476 <input type="submit" name="login" />
477 </form>
478
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
479 .. tip::
480
481 The ``error`` variable passed into the template is an instance of
482 :class:`Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException`.
483 It may contain more information - or even sensitive information - about
484 the authentication failure, so use it wisely!
485
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
486 The form has very few requirements. First, by submitting the form to ``/login_check``
487 (via the ``login_check`` route), the security system will intercept the form
488 submission and process the form for you automatically. Second, the security
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
489 system expects the submitted fields to be called ``_username`` and ``_password``
a85bae3 @weaverryan Tweaking the excellent new securing_services cookbook entry
weaverryan authored Jun 6, 2011
490 (these field names can be :ref:`configured<reference-security-firewall-form-login>`).
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
491
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
492 And that's it! When you submit the form, the security system will automatically
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
493 check the user's credentials and either authenticate the user or send the
494 user back to the login form where the error can be displayed.
495
496 Let's review the whole process:
497
498 #. The user tries to access a resource that is protected;
499 #. The firewall initiates the authentication process by redirecting the
500 user to the login form (``/login``);
501 #. The ``/login`` page renders login form via the route and controller created
502 in this example;
503 #. The user submits the login form to ``/login_check``;
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
504 #. The security system intercepts the request, checks the user's submitted
505 credentials, authenticates the user if they are correct, and sends the
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
506 user back to the login form if they are not.
507
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
508 By default, if the submitted credentials are correct, the user will be redirected
509 to the original page that was requested (e.g. ``/admin/foo``). If the user
510 originally went straight to the login page, he'll be redirected to the homepage.
511 This can be highly customized, allowing you to, for example, redirect the
512 user to a specific URL.
513
514 For more details on this and how to customize the form login process in general,
515 see :doc:`/cookbook/security/form_login`.
516
a85bae3 @weaverryan Tweaking the excellent new securing_services cookbook entry
weaverryan authored Jun 6, 2011
517 .. _book-security-common-pitfalls:
518
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
519 .. sidebar:: Avoid Common Pitfalls
520
521 When setting up your login form, watch out for a few common pitfalls.
522
523 **1. Create the correct routes**
524
525 First, be sure that you've defined the ``/login`` and ``/login_check``
526 routes correctly and that they correspond to the ``login_path`` and
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
527 ``check_path`` config values. A misconfiguration here can mean that you're
528 redirected to a 404 page instead of the login page, or that submitting
529 the login form does nothing (you just see the login form over and over
530 again).
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
531
532 **2. Be sure the login page isn't secure**
533
534 Also, be sure that the login page does *not* require any roles to be
535 viewed. For example, the following configuration - which requires the
536 ``ROLE_ADMIN`` role for all URLs (including the ``/login`` URL), will
537 cause a redirect loop:
538
539 .. configuration-block::
540
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
541 .. code-block:: yaml
542
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
543 access_control:
544 - { path: ^/, roles: ROLE_ADMIN }
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
545
546 .. code-block:: xml
547
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
548 <access-control>
549 <rule path="^/" role="ROLE_ADMIN" />
550 </access-control>
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
551
552 .. code-block:: php
553
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
554 'access_control' => array(
555 array('path' => '^/', 'role' => 'ROLE_ADMIN'),
556 ),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
557
558 Removing the access control on the ``/login`` URL fixes the problem:
559
560 .. configuration-block::
561
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
562 .. code-block:: yaml
563
564 access_control:
565 - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
566 - { path: ^/, roles: ROLE_ADMIN }
567
568 .. code-block:: xml
569
570 <access-control>
571 <rule path="^/login" role="IS_AUTHENTICATED_ANONYMOUSLY" />
572 <rule path="^/" role="ROLE_ADMIN" />
573 </access-control>
574
575 .. code-block:: php
576
577 'access_control' => array(
578 array('path' => '^/login', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'),
579 array('path' => '^/', 'role' => 'ROLE_ADMIN'),
580 ),
581
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
582 Also, if your firewall does *not* allow for anonymous users, you'll need
583 to create a special firewall that allows anonymous users for the login
584 page:
585
586 .. configuration-block::
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
587
588 .. code-block:: yaml
589
590 firewalls:
591 login_firewall:
65c5e15 @weaverryan [book][security] Fixing two errors per @stof
weaverryan authored May 16, 2011
592 pattern: ^/login$
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
593 anonymous: ~
594 secured_area:
595 pattern: ^/
596 login_form: ~
597
598 .. code-block:: xml
599
65c5e15 @weaverryan [book][security] Fixing two errors per @stof
weaverryan authored May 16, 2011
600 <firewall name="login_firewall" pattern="^/login$">
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
601 <anonymous />
602 </firewall>
603 <firewall name="secured_area" pattern="^/">
604 <login_form />
605 </firewall>
606
607 .. code-block:: php
608
609 'firewalls' => array(
610 'login_firewall' => array(
65c5e15 @weaverryan [book][security] Fixing two errors per @stof
weaverryan authored May 16, 2011
611 'pattern' => '^/login$',
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
612 'anonymous' => array(),
613 ),
614 'secured_area' => array(
615 'pattern' => '^/',
616 'form_login' => array(),
617 ),
618 ),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
619
620 **3. Be sure ``/login_check`` is behind a firewall**
621
49e39db @weaverryan [book][security] Other changes per @stof
weaverryan authored May 11, 2011
622 Next, make sure that your ``check_path`` URL (e.g. ``/login_check``)
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
623 is behind the firewall you're using for your form login (in this example,
624 the single firewall matches *all* URLs, including ``/login_check``). If
625 ``/login_check`` doesn't match any firewall, you'll receive a ``Unable
626 to find the controller for path "/login_check"`` exception.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
627
49e39db @weaverryan [book][security] Other changes per @stof
weaverryan authored May 12, 2011
628 **4. Multiple firewalls don't share security context**
629
630 If you're using multiple firewalls and you authenticate against one firewall,
631 you will *not* be authenticated against any other firewalls automatically.
632 Different firewalls are like different security systems. That's why,
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
633 for most applications, having one main firewall is enough.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
634
635 Authorization
636 -------------
637
638 The first step in security is always authentication: the process of verifying
639 who the user is. With Symfony, authentication can be done in any way - via
640 a form login, basic HTTP Authentication, or even via Facebook.
641
642 Once the user has been authenticated, authorization begins. Authorization
643 provides a standard and powerful way to decide if a user can access any resource
644 (a URL, a model object, a method call, ...). This works by assigning specific
645 roles to each user, and then requiring different roles for different resources.
646
647 The process of authorization has two different sides:
648
649 #. The user has a specific set of roles;
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
650 #. A resource requires a specific role in order to be accessed.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
651
652 In this section, you'll focus on how to secure different resources (e.g. URLs,
653 method calls, etc) with different roles. Later, you'll learn more about how
654 roles are created and assigned to users.
655
656 Securing Specific URL Patterns
657 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
658
659 The most basic way to secure part of your application is to secure an entire
660 URL pattern. You've seen this already in the first example of this chapter,
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
661 where anything matching the regular expression pattern ``^/admin`` requires
662 the ``ROLE_ADMIN`` role.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
663
664 You can define as many URL patterns as you need - each is a regular expression.
665
666 .. configuration-block::
667
668 .. code-block:: yaml
669
670 # app/config/config.yml
671 security:
672 # ...
673 access_control:
674 - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
675 - { path: ^/admin, roles: ROLE_ADMIN }
676
677 .. code-block:: xml
678
679 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
680 <config>
681 <!-- ... -->
682 <access-control>
683 <rule path="^/admin/users" role="ROLE_SUPER_ADMIN" />
684 <rule path="^/admin" role="ROLE_ADMIN" />
685 </access-control>
686 </config>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
687
688 .. code-block:: php
689
690 // app/config/config.php
691 $container->loadFromExtension('security', array(
692 // ...
693 'access_control' => array(
694 array('path' => '^/admin/users', 'role' => 'ROLE_SUPER_ADMIN'),
695 array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
696 ),
697 ));
698
699 .. tip::
700
701 Prepending the path with ``^`` ensures that only URLs *beginning* with
702 the pattern are matched. For example, a path of simply ``/admin`` would
703 match ``/admin/foo`` but also ``/foo/admin``.
704
705 For each incoming request, Symfony2 tries to find a matching access control
706 rule (the first one wins). If the user isn't authenticated yet, the authentication
707 process is initiated (i.e. the user is given a chance to login). However,
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
708 if the user *is* authenticated but doesn't have the required role, an
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
709 :class:`Symfony\\Component\Security\\Core\\Exception\\AccessDeniedException`
710 exception is thrown, which you can handle and turn into a nice "access denied"
711 error page for the user. See :doc:`/cookbook/controller/error_pages` for
712 more information.
713
714 Since Symfony uses the first access control rule it matches, a URL like ``/admin/users/new``
715 will match the first rule and require only the ``ROLE_SUPER_ADMIN`` role.
716 Any URL like ``/admin/blog`` will match the second rule and require ``ROLE_ADMIN``.
717
718 You can also force ``HTTP`` or ``HTTPS`` via an ``access_control`` entry.
719 For more information, see :doc:`/cookbook/security/force_https`.
720
a85bae3 @weaverryan Tweaking the excellent new securing_services cookbook entry
weaverryan authored Jun 6, 2011
721 .. _book-security-securing-controller:
722
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
723 Securing a Controller
724 ~~~~~~~~~~~~~~~~~~~~~
725
726 Protecting your application based on URL patterns is easy, but may not be
727 fine-grained enough in certain cases. When necessary, you can easily force
728 authorization from inside a controller:
729
730 .. code-block:: php
731
058844d @weaverryan [book][security] Adding namespace so that an example is more usable
weaverryan authored May 14, 2011
732 use Symfony\Component\Security\Core\Exception\AccessDeniedException
733 // ...
734
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
735 public function helloAction($name)
736 {
737 if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
738 throw new AccessDeniedException();
739 }
740
741 // ...
742 }
743
a85bae3 @weaverryan Tweaking the excellent new securing_services cookbook entry
weaverryan authored Jun 6, 2011
744 .. _book-security-securing-controller-annotations:
745
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
746 You can also choose to install and use the optional ``SecurityExtraBundle``,
747 which can secure your controller using annotations:
748
749 .. code-block:: php
750
06f3bcb @fabpot updated annotations
fabpot authored May 22, 2011
751 use JMS\SecurityExtraBundle\Annotation\Secure;
752
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
753 /**
06f3bcb @fabpot updated annotations
fabpot authored May 22, 2011
754 * @Secure(roles="ROLE_ADMIN")
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
755 */
756 public function helloAction($name)
757 {
758 // ...
759 }
760
761 For more information, see the `SecurityExtraBundle`_ documentation. If you're
762 using Symfony's Standard Distribution, this bundle is available by default.
763 If not, you can easily download and install it.
764
765 Securing other Services
766 ~~~~~~~~~~~~~~~~~~~~~~~
767
768 In fact, anything in Symfony can be protected using a strategy similar to
769 the one seen in the previous section. For example, suppose you have a service
770 (i.e. a PHP class) whose job is to send emails from one user to another.
771 You can restrict use of this class - no matter where it's being used from -
772 to users that have a specific role.
773
774 For more information on how you can use the security component to secure
775 different services and methods in your application, see :doc:`/cookbook/security/securing_services`.
776
777 Access Control Lists (ACLs): Securing Individual Database Objects
778 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
779
780 Imagine you are designing a blog system where your users can comment on your
781 posts. Now, you want a user to be able to edit his own comments, but not
782 those of other users. Also, as the admin user, you yourself want to be able
783 to edit *all* comments.
784
785 The security component comes with an optional access control list (ACL) system
786 that you can use when you need to control access to individual instances
787 of an object in your system. *Without* ACL, you can secure your system so that
788 only certain users can edit blog comments in general. But *with* ACL, you
789 can restrict or allow access on a comment-by-comment basis.
790
791 For more information, see the cookbook article: :doc:`/cookbook/security/acl`.
792
793 Users
794 -----
795
796 In the previous sections, you learned how you can protect different resources
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
797 by requiring a set of *roles* for a resource. In this section we'll explore
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
798 the other side of authorization: users.
799
800 Where do Users come from? (*User Providers*)
801 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
802
803 During authentication, the user submits a set of credentials (usually a username
804 and password). The job of the authentication system is to match those credentials
805 against some pool of users. So where does this list of users come from?
806
807 In Symfony2, users can come from anywhere - a configuration file, a database
808 table, a web service, or anything else you can dream up. Anything that provides
809 one or more users to the authentication system is known as a "user provider".
810 Symfony2 comes standard with the two most common user providers: one that
811 loads users from a configuration file and one that loads users from a database
812 table.
813
814 Specifying Users in a Configuration File
815 ........................................
816
817 The easiest way to specify your users is directly in a configuration file.
818 In fact, you've seen this already in the example in this chapter.
819
820 .. configuration-block::
821
822 .. code-block:: yaml
823
824 # app/config/config.yml
825 security:
826 # ...
827 providers:
828 default_provider:
829 users:
830 ryan: { password: ryanpass, roles: 'ROLE_USER' }
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
831 admin: { password: kitten, roles: 'ROLE_ADMIN' }
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
832
833 .. code-block:: xml
834
835 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
836 <config>
837 <!-- ... -->
838 <provider name="default_provider">
839 <user name="ryan" password="ryanpass" roles="ROLE_USER" />
840 <user name="admin" password="kitten" roles="ROLE_ADMIN" />
841 </provider>
842 </config>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
843
844 .. code-block:: php
845
846 // app/config/config.php
847 $container->loadFromExtension('security', array(
848 // ...
849 'providers' => array(
850 'default_provider' => array(
851 'users' => array(
852 'ryan' => array('password' => 'ryanpass', 'roles' => 'ROLE_USER'),
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
853 'admin' => array('password' => 'kitten', 'roles' => 'ROLE_ADMIN'),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
854 ),
855 ),
856 ),
857 ));
858
859 This user provider is called the "in-memory" user provider, since the users
860 aren't stored anywhere in a database. The actual user object is provided
861 by Symfony (:class:`Symfony\\Component\\Security\\Core\\User\\User`).
862
863 .. tip::
864 Any user provider can load users directly from configuration by specifying
865 the ``users`` configuration parameter and listing the users beneath it.
866
cb295cf @weaverryan [book][security] Added caution about users with numbers or dashes. Cl…
weaverryan authored Jun 1, 2011
867 .. caution::
868
869 If your username is completely numeric (e.g. ``77``) or contains a dash
870 (e.g. ``user-name``), you should use that alternative syntax when specifying
871 users in YAML:
872
873 .. code-block:: yaml
874
875 users:
876 - { name: 77, password: pass, roles: 'ROLE_USER' }
877 - { name: user-name, password: pass, roles: 'ROLE_USER' }
878
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
879 For smaller sites, this method is quick and easy to setup. For more complex
880 systems, you'll want to load your users from the database.
881
882 Loading Users from the Database
883 ...............................
884
885 If you'd like to load your users via the Doctrine ORM, you can easily do
886 this by creating a ``User`` class and configuring the ``entity`` provider.
887
888 .. tip:
889
890 A high-quality open source bundle is available that allows your users
49e39db @weaverryan [book][security] Other changes per @stof
weaverryan authored May 12, 2011
891 to be stored via the Doctrine ORM or ODM. Read more about the `FOSUserBundle`_
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
892 on GitHub.
893
894 With this approach, you'll first create your own ``User`` class, which will
895 be stored in the database.
896
897 .. code-block:: php
898
899 // src/Acme/UserBundle/Entity/User.php
900 namespace Acme\UserBundle\Entity;
06f3bcb @fabpot updated annotations
fabpot authored May 22, 2011
901
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
902 use Symfony\Component\Security\Core\User\UserInterface;
06f3bcb @fabpot updated annotations
fabpot authored May 22, 2011
903 use Doctrine\ORM\Mapping as ORM;
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
904
905 /**
06f3bcb @fabpot updated annotations
fabpot authored May 22, 2011
906 * @ORM\Entity
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
907 */
908 class User implements UserInterface
909 {
910 /**
06f3bcb @fabpot updated annotations
fabpot authored May 22, 2011
911 * @ORM\Column(type="string", length="255")
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
912 */
913 protected $username;
914
915 // ...
916 }
917
918 As far as the security system is concerned, the only requirement for your
919 custom user class is that it implements the :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface`
920 interface. This means that your concept of a "user" can be anything, as long
921 as it implements this interface.
922
424b2e5 @weaverryan [book][security] Small fix
weaverryan authored Jun 2, 2011
923 .. note::
8f2687e @schmittjoh added a note about serialization
schmittjoh authored Jun 1, 2011
924
424b2e5 @weaverryan [book][security] Small fix
weaverryan authored Jun 2, 2011
925 The user object will be serialized and saved in the session during requests,
926 therefore it is recommended that you `implement the \Serializable interface`_
927 in your user object.
8f2687e @schmittjoh added a note about serialization
schmittjoh authored Jun 1, 2011
928
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
929 Next, configure an ``entity`` user provider, and point it to your ``User``
930 class:
931
932 .. configuration-block::
933
934 .. code-block:: yaml
935
936 # app/config/security.yml
937 security:
938 providers:
939 main:
940 entity: { class: Acme\UserBundle\Entity\User, property: username }
941
942 .. code-block:: xml
943
944 <!-- app/config/security.xml -->
945 <config>
946 <provider name="main">
947 <entity class="Acme\UserBundle\Entity\User" property="username" />
948 </provider>
949 </config>
950
951 .. code-block:: php
952
953 // app/config/security.php
954 $container->loadFromExtension('security', array(
955 'providers' => array(
956 'main' => array(
957 'entity' => array('class' => 'Acme\UserBundle\Entity\User', 'property' => 'username'),
958 ),
959 ),
960 ));
961
962 With the introduction of this new provider, the authentication system will
963 attempt to load a ``User`` object from the database by using the ``username``
964 field of that class.
965
966 .. note::
967 This example is just meant to show you the basic idea behind the ``entity``
968 provider. For a full working example, see :doc:`/cookbook/security/entity_provider`.
969
970 For more information on creating your own custom provider (e.g. if you needed
971 to load users via a web service), see :doc:`/cookbook/security/custom_provider`.
972
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
973 Encoding the User's Password
974 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
975
976 So far, for simplicity, all the examples have stored the users' passwords
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
977 in plain text (whether those users are stored in a configuration file or in
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
978 a database somewhere). Of course, in a real application, you'll want to encode
979 your users' passwords for security reasons. This is easily accomplished by
980 mapping your User class to one of several built-in "encoders". For example,
981 to store your users in memory, but obscure their passwords via ``sha1``,
982 do the following:
983
984 .. configuration-block::
985
986 .. code-block:: yaml
987
988 # app/config/config.yml
989 security:
990 # ...
991 providers:
992 in_memory:
993 users:
994 ryan: { password: bb87a29949f3a1ee0559f8a57357487151281386, roles: 'ROLE_USER' }
995 admin: { password: 74913f5cd5f61ec0bcfdb775414c2fb3d161b620, roles: 'ROLE_ADMIN' }
996
997 encoders:
998 Symfony\Component\Security\Core\User\User:
999 algorithm: sha1
1000 iterations: 1
1001 encode_as_base64: false
1002
1003 .. code-block:: xml
1004
1005 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1006 <config>
1007 <!-- ... -->
1008 <provider name="in_memory">
1009 <user name="ryan" password="bb87a29949f3a1ee0559f8a57357487151281386" roles="ROLE_USER" />
1010 <user name="admin" password="74913f5cd5f61ec0bcfdb775414c2fb3d161b620" roles="ROLE_ADMIN" />
1011 </provider>
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1012
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1013 <encoder class="Symfony\Component\Security\Core\User\User" algorithm="sha1" iterations="1" encode_as_base64="false" />
1014 </config>
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1015
1016 .. code-block:: php
1017
1018 // app/config/config.php
1019 $container->loadFromExtension('security', array(
1020 // ...
1021 'providers' => array(
1022 'in_memory' => array(
1023 'users' => array(
1024 'ryan' => array('password' => 'bb87a29949f3a1ee0559f8a57357487151281386', 'roles' => 'ROLE_USER'),
1025 'admin' => array('password' => '74913f5cd5f61ec0bcfdb775414c2fb3d161b620', 'roles' => 'ROLE_ADMIN'),
1026 ),
1027 ),
1028 ),
1029 'encoders' => array(
1030 'Symfony\Component\Security\Core\User\User' => array(
1031 'algorithm' => 'sha1',
1032 'iterations' => 1,
1033 'encode_as_base64' => false,
1034 ),
1035 ),
1036 ));
1037
1038 By setting the ``iterations`` to ``1`` and the ``encode_as_base64`` to false,
1039 the password is simply run through the ``sha1`` algorithm one time and without
1040 any extra encoding. You can now calculate the hashed password either programmatically
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1041 (e.g. ``hash('sha1', 'ryanpass')``) or via some online tool like `functions-online.com`_
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1042
1043 If you're creating your users dynamically (and storing them in a database),
1044 you can use even tougher hashing algorithms and then rely on an actual password
1045 encoder object to help you encode passwords. For example, suppose your User
1046 object is ``Acme\UserBundle\Entity\User`` (like in the above example). First,
1047 configure the encoder for that user:
1048
1049 .. configuration-block::
1050
1051 .. code-block:: yaml
1052
1053 # app/config/config.yml
1054 security:
1055 # ...
1056
1057 encoders:
1058 Acme\UserBundle\Entity\User: sha512
1059
1060 .. code-block:: xml
1061
1062 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1063 <config>
1064 <!-- ... -->
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1065
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1066 <encoder class="Acme\UserBundle\Entity\User" algorithm="sha512" />
1067 </config>
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1068
1069 .. code-block:: php
1070
1071 // app/config/config.php
1072 $container->loadFromExtension('security', array(
1073 // ...
1074
1075 'encoders' => array(
1076 'Acme\UserBundle\Entity\User' => 'sha512',
1077 ),
1078 ));
1079
1080 In this case, you're using the stronger ``sha512`` algorithm. Also, since
1081 you've simply specified the algorithm (``sha512``) as a string, the system
1082 will default to hashing your password 5000 times in a row and then encoding
1083 it as base64. In other words, the password has been greatly obfuscated so
1084 that the hashed password can't be decoded (i.e. you can't determine the password
1085 from the hashed password).
1086
1087 If you have some sort of registration form for users, you'll need to be able
1088 to determine the hashed password so that you can set it on your user. No
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1089 matter what algorithm you configure for your user object, the hashed password
1090 can always be determined in the following way from a controller:
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1091
1092 .. code-block:: php
1093
1094 $factory = $this->get('security.encoder_factory');
1095 $user = new Acme\UserBundle\Entity\User();
1096
1097 $encoder = $factory->getEncoder($user);
1098 $password = $encoder->encodePassword('ryanpass', $user->getSalt());
1099 $user->setPassword($password);
1100
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1101 Retrieving the User Object
1102 ~~~~~~~~~~~~~~~~~~~~~~~~~~
1103
1104 After authentication, the ``User`` object of the current user can be accessed
1105 via the ``security.context`` service. From inside a controller, this will
1106 look like:
1107
1108 .. code-block:: php
1109
1110 public function indexAction()
1111 {
1112 $user = $this->get('security.context')->getToken()->getUser();
1113 }
1114
1115 .. note::
1116
1117 Anonymous users are technically authenticated, meaning that the ``isAuthenticated()``
49e39db @weaverryan [book][security] Other changes per @stof
weaverryan authored May 12, 2011
1118 method of an anonymous user object will return true. To check if your
1119 user is actually authenticated, check for the ``IS_AUTHENTICATED_FULLY``
1120 role.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1121
1122 Using Multiple User Providers
1123 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1124
1125 Each authentication mechanism (e.g. HTTP Authentication, form login, etc)
1126 uses exactly one user provider, and will use the first declared user provider
1127 by default. But what if you want to specify a few users via configuration
1128 and the rest of your users in the database? This is possible by creating
1129 a new provider that chains the two together:
1130
1131 .. configuration-block::
1132
1133 .. code-block:: yaml
1134
1135 # app/config/security.yml
1136 security:
1137 providers:
1138 chain_provider:
1139 providers: [in_memory, user_db]
1140 in_memory:
1141 users:
1142 foo: { password: test }
1143 user_db:
1144 entity: { class: Acme\UserBundle\Entity\User, property: username }
1145
1146 .. code-block:: xml
1147
1148 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1149 <config>
1150 <provider name=="chain_provider">
1151 <provider>in_memory</provider>
1152 <provider>user_db</provider>
1153 </provider>
1154 <provider name="in_memory">
1155 <user name="foo" password="test" />
1156 </provider>
1157 <provider name="user_db">
1158 <entity class="Acme\UserBundle\Entity\User" property="username" />
1159 </provider>
1160 </config>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1161
1162 .. code-block:: php
1163
1164 // app/config/config.php
1165 $container->loadFromExtension('security', array(
1166 'providers' => array(
1167 'chain_provider' => array(
1168 'providers' => array('in_memory', 'user_db'),
1169 ),
1170 'in_memory' => array(
1171 'users' => array(
1172 'foo' => array('password' => 'test'),
1173 ),
1174 ),
1175 'user_db' => array(
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1176 'entity' => array('class' => 'Acme\UserBundle\Entity\User', 'property' => 'username'),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1177 ),
1178 ),
1179 ));
1180
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1181 Now, all authentication mechanisms will use the ``chain_provider``, since
1182 it's the first specified. The ``chain_provider`` will, in turn, try to load
1183 the user from both the ``in_memory`` and ``user_db`` providers.
1184
1185 .. tip::
1186
1187 If you have no reasons to separate your ``in_memory`` users from your
1188 ``user_db`` users, you can accomplish this even more easily by combining
1189 the two sources into a single provider:
1190
1191 .. configuration-block::
1192
1193 .. code-block:: yaml
1194
1195 # app/config/security.yml
1196 security:
1197 providers:
1198 main_provider:
1199 users:
1200 foo: { password: test }
1201 entity: { class: Acme\UserBundle\Entity\User, property: username }
1202
1203 .. code-block:: xml
1204
1205 <!-- app/config/config.xml -->
1206 <config>
1207 <provider name=="main_provider">
1208 <user name="foo" password="test" />
1209 <entity class="Acme\UserBundle\Entity\User" property="username" />
1210 </provider>
1211 </config>
1212
1213 .. code-block:: php
1214
1215 // app/config/config.php
1216 $container->loadFromExtension('security', array(
1217 'providers' => array(
1218 'main_provider' => array(
1219 'users' => array(
1220 'foo' => array('password' => 'test'),
1221 ),
1222 'entity' => array('class' => 'Acme\UserBundle\Entity\User', 'property' => 'username'),
1223 ),
1224 ),
1225 ));
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1226
1227 You can also configure the firewall or individual authentication mechanisms
1228 to use a specific provider. Again, unless a provider is specified explicitly,
1229 the first provider is always used:
1230
1231 .. configuration-block::
1232
1233 .. code-block:: yaml
1234
1235 # app/config/config.yml
1236 security:
1237 firewalls:
1238 secured_area:
1239 # ...
1240 provider: user_db
1241 http_basic:
1242 realm: "Secured Demo Area"
1243 provider: in_memory
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1244 form_login: ~
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1245
1246 .. code-block:: xml
1247
1248 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1249 <config>
1250 <firewall name="secured_area" pattern="^/" provider="user_db">
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1251 <!-- ... -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1252 <http-basic realm="Secured Demo Area" provider="in_memory" />
1253 <form-login />
1254 </firewall>
1255 </config>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1256
1257 .. code-block:: php
1258
1259 // app/config/config.php
1260 $container->loadFromExtension('security', array(
1261 'firewalls' => array(
1262 'secured_area' => array(
1263 // ...
1264 'provider' => 'user_db',
1265 'http_basic' => array(
1266 // ...
1267 'provider' => 'in_memory',
1268 ),
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1269 'form_login' => array(),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1270 ),
1271 ),
1272 ));
1273
1274 In this example, if a user tries to login via HTTP authentication, the authentication
1275 system will use the ``in_memory`` user provider. But if the user tries to
1276 login via the form login, the ``user_db`` provider will be used (since it's
1277 the default for the firewall as a whole).
1278
1279 For more information about user provider and firewall configuration, see
1280 the :doc:`/reference/configuration/security`.
1281
1282 Roles
1283 -----
1284
1285 The idea of a "role" is key to the authorization process. Each user is assigned
1286 a set of roles and then each resource requires one or more roles. If the user
1287 has the required roles, access is granted. Otherwise access is denied.
1288
1289 Roles are pretty simple, and are basically strings that you can invent and
1290 use as needed (though roles are objects internally). For example, if you
1291 need to start limiting access to the blog admin section of your website,
1292 you could protect that section using a ``ROLE_BLOG_ADMIN`` role. This role
1293 doesn't need to be defined anywhere - you can just start using it.
1294
1295 .. note::
1296
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1297 All roles **must** begin with the ``ROLE_`` prefix to be managed by
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1298 Symfony2. If you define your own roles with a dedicated ``Role`` class
1299 (more advanced), don't use the ``ROLE_`` prefix.
1300
1301 Hierarchical Roles
1302 ~~~~~~~~~~~~~~~~~~
1303
1304 Instead of associating many roles to users, you can define role inheritance
1305 rules by creating a role hierarchy:
1306
1307 .. configuration-block::
1308
1309 .. code-block:: yaml
1310
1311 # app/config/security.yml
1312 security:
1313 role_hierarchy:
1314 ROLE_ADMIN: ROLE_USER
19191ff @weaverryan [book][security] Small change per @stof
weaverryan authored May 11, 2011
1315 ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1316
1317 .. code-block:: xml
1318
1319 <!-- app/config/security.xml -->
1320 <config>
1321 <role-hierarchy>
1322 <role id="ROLE_ADMIN">ROLE_USER</role>
19191ff @weaverryan [book][security] Small change per @stof
weaverryan authored May 12, 2011
1323 <role id="ROLE_SUPER_ADMIN">ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH</role>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1324 </role-hierarchy>
1325 </config>
1326
1327 .. code-block:: php
1328
1329 // app/config/security.php
1330 $container->loadFromExtension('security', array(
1331 'role_hierarchy' => array(
1332 'ROLE_ADMIN' => 'ROLE_USER',
19191ff @weaverryan [book][security] Small change per @stof
weaverryan authored May 12, 2011
1333 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1334 ),
1335 ));
1336
19191ff @weaverryan [book][security] Small change per @stof
weaverryan authored May 12, 2011
1337 In the above configuration, users with ``ROLE_ADMIN`` role will also have the
1338 ``ROLE_USER`` role. The ``ROLE_SUPER_ADMIN`` role has ``ROLE_ADMIN``, ``ROLE_ALLOWED_TO_SWITCH``
1339 and ``ROLE_USER`` (inherited from ``ROLE_ADMIN``).
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1340
1341 Logging Out
1342 -----------
1343
1344 Usually, you'll also want your users to be able to log out. Fortunately,
1345 the firewall can handle this automatically for you when you activate the
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1346 ``logout`` config parameter:
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1347
1348 .. configuration-block::
1349
1350 .. code-block:: yaml
1351
1352 # app/config/config.yml
1353 security:
1354 firewalls:
1355 secured_area:
1356 # ...
1357 logout:
1358 path: /logout
1359 target: /
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1360 # ...
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1361
1362 .. code-block:: xml
1363
1364 <!-- app/config/config.xml -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1365 <config>
1366 <firewall name="secured_area" pattern="^/">
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1367 <!-- ... -->
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1368 <logout path="/logout" target="/" />
1369 </firewall>
1370 <!-- ... -->
1371 </config>
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1372
1373 .. code-block:: php
1374
1375 // app/config/config.php
1376 $container->loadFromExtension('security', array(
1377 'firewalls' => array(
1378 'secured_area' => array(
1379 // ...
0561c2c @weaverryan [book][security] A few tweaks per @stof
weaverryan authored May 12, 2011
1380 'logout' => array('path' => 'logout', 'target' => '/'),
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1381 ),
1382 ),
1383 // ...
1384 ));
1385
1386 Once this is configured under your firewall, sending a user to ``/logout``
2e88d91 @adrienbrault Fixed mistake
adrienbrault authored Jun 1, 2011
1387 (or whatever you configure the ``path`` to be), will un-authenticate the
0561c2c @weaverryan [book][security] A few tweaks per @stof
weaverryan authored May 12, 2011
1388 current user. The user will then be sent to the homepage (the value defined
1389 by the ``target`` parameter). Both the ``path`` and ``target`` config parameters
1390 default to what's specified here. In other words, unless you need to customize
1391 them, you can omit them entirely and shorten your configuration:
1392
1393 .. configuration-block::
1394
1395 .. code-block:: yaml
1396
1397 logout: ~
1398
1399 .. code-block:: xml
1400
1401 <logout />
1402
1403 .. code-block:: php
1404
1405 'logout' => array(),
1406
1407 Note that you will *not* need to implement a controller for the ``/logout``
1408 URL as the firewall takes care of everything. You may, however, want to create
1409 a route so that you can use it to generate the URL:
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1410
1411 .. configuration-block::
1412
1413 .. code-block:: yaml
1414
1415 # app/config/routing.yml
1416 logout:
1417 pattern: /logout
1418
1419 .. code-block:: xml
1420
1421 <!-- app/config/routing.xml -->
1422 <?xml version="1.0" encoding="UTF-8" ?>
1423
1424 <routes xmlns="http://symfony.com/schema/routing"
1425 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1426 xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
1427
1428 <route id="logout" pattern="/logout" />
1429
1430 </routes>
1431
1432 .. code-block:: php
1433
1434 // app/config/routing.php
1435 use Symfony\Component\Routing\RouteCollection;
1436 use Symfony\Component\Routing\Route;
1437
1438 $collection = new RouteCollection();
1439 $collection->add('logout', new Route('/logout', array()));
1440
1441 return $collection;
1442
1443 Once the user has been logged out, he will be redirected to whatever path
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1444 is defined by the ``target`` parameter above (e.g. the ``homepage``). For
1445 more information on configuring the logout, see the
3e99456 @weaverryan [book][security] Proofreading security chapter, adding some placehold…
weaverryan authored May 14, 2011
1446 :doc:`Security Configuration Reference</reference/configuration/security>`.
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1447
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1448 Access Control in Templates
1449 ---------------------------
1450
1451 If you want to check if the current user has a role inside a template, use
1452 the built-in helper function:
1453
1454 .. configuration-block::
1455
1456 .. code-block:: html+jinja
1457
1458 {% if is_granted('ROLE_ADMIN') %}
1459 <a href="...">Delete</a>
1460 {% endif %}
1461
1462 .. code-block:: html+php
1463
1464 <?php if ($view['security']->isGranted('ROLE_ADMIN')): ?>
1465 <a href="...">Delete</a>
1466 <?php endif; ?>
1467
eca314f @weaverryan [book][security] Adding note per @stof about access control without a…
weaverryan authored May 12, 2011
1468 .. note::
1469
1470 If you use this function and are *not* at a URL where there is a firewall
1471 active, an exception will be thrown. Again, it's almost always a good
1472 idea to have a main firewall that covers all URLs (as has been shown
1473 in this chapter).
1474
53b08ad @weaverryan [book][security] Porting a small section from the current docs courte…
weaverryan authored May 11, 2011
1475 Access Control in Controllers
1476 -----------------------------
1477
1478 If you want to check if the current user has a role in your controller, use
1479 the ``isGranted`` method of the security context:
1480
1481 .. code-block:: php
1482
1483 public function indexAction()
1484 {
1485 // show different content to admin users
1486 if($this->get('security.context')->isGranted('ADMIN')) {
1487 // Load admin content here
1488 }
1489 // load other regular content here
1490 }
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1491
eca314f @weaverryan [book][security] Adding note per @stof about access control without a…
weaverryan authored May 12, 2011
1492 .. note::
1493
1494 A firewall must be active or an exception will be thrown when the ``isGranted``
1495 method is called. See the note above about templates for more details.
1496
9b8664d @weaverryan [book][security] Migrating over the impersonation section
weaverryan authored May 11, 2011
1497 Impersonating a User
1498 --------------------
1499
1500 Sometimes, it's useful to be able to switch from one user to another without
1501 having to logout and login again (for instance when you are debugging or trying
1502 to understand a bug a user sees that you can't reproduce). This can be easily
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1503 done by activating the ``switch_user`` firewall listener:
9b8664d @weaverryan [book][security] Migrating over the impersonation section
weaverryan authored May 11, 2011
1504
1505 .. configuration-block::
1506
1507 .. code-block:: yaml
1508
1509 # app/config/security.yml
1510 security:
1511 firewalls:
1512 main:
1513 # ...
1514 switch_user: true
1515
1516 .. code-block:: xml
1517
1518 <!-- app/config/security.xml -->
1519 <config>
1520 <firewall>
1521 <!-- ... -->
1522 <switch-user />
1523 </firewall>
1524 </config>
1525
1526 .. code-block:: php
1527
1528 // app/config/security.php
1529 $container->loadFromExtension('security', array(
1530 'firewalls' => array(
1531 'main'=> array(
1532 // ...
1533 'switch_user' => true
1534 ),
1535 ),
1536 ));
1537
1538 To switch to another user, just add a query string with the ``_switch_user``
1539 parameter and the username as the value to the current URL:
1540
1541 http://example.com/somewhere?_switch_user=thomas
1542
1543 To switch back to the original user, use the special ``_exit`` username:
1544
1545 http://example.com/somewhere?_switch_user=_exit
1546
1547 Of course, this feature needs to be made available to a small group of users.
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1548 By default, access is restricted to users having the ``ROLE_ALLOWED_TO_SWITCH``
9b8664d @weaverryan [book][security] Migrating over the impersonation section
weaverryan authored May 11, 2011
1549 role. The name of this role can be modified via the ``role`` setting. For
1550 extra security, you can also change the query parameter name via the ``parameter``
1551 setting:
1552
1553 .. configuration-block::
1554
1555 .. code-block:: yaml
1556
1557 # app/config/security.yml
1558 security:
1559 firewalls:
1560 main:
1561 // ...
1562 switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
1563
1564 .. code-block:: xml
1565
1566 <!-- app/config/security.xml -->
1567 <config>
1568 <firewall>
1569 <!-- ... -->
1570 <switch-user role="ROLE_ADMIN" parameter="_want_to_be_this_user" />
1571 </firewall>
1572 </config>
1573
1574 .. code-block:: php
1575
1576 // app/config/security.php
1577 $container->loadFromExtension('security', array(
1578 'firewalls' => array(
1579 'main'=> array(
1580 // ...
1581 'switch_user' => array('role' => 'ROLE_ADMIN', 'parameter' => '_want_to_be_this_user'),
1582 ),
1583 ),
1584 ));
1585
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
1586 Stateless Authentication
1587 ------------------------
1588
1589 By default, Symfony2 relies on a cookie (the Session) to persist the security
1590 context of the user. But if you use certificates or HTTP authentication for
1591 instance, persistence is not needed as credentials are available for each
1592 request. In that case, and if you don't need to store anything else between
1593 requests, you can activate the stateless authentication (which means that no
1594 cookie will be ever created by Symfony2):
1595
1596 .. configuration-block::
1597
1598 .. code-block:: yaml
1599
1600 # app/config/security.yml
1601 security:
1602 firewalls:
1603 main:
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1604 http_basic: ~
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
1605 stateless: true
1606
1607 .. code-block:: xml
1608
1609 <!-- app/config/security.xml -->
1610 <config>
1611 <firewall stateless="true">
1612 <http-basic />
1613 </firewall>
1614 </config>
1615
1616 .. code-block:: php
1617
1618 // app/config/security.php
1619 $container->loadFromExtension('security', array(
1620 'firewalls' => array(
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1621 'main' => array('http_basic' => array(), 'stateless' => true),
9e4a875 @weaverryan [book][security] Making several fixes per @stof and adding a section …
weaverryan authored May 12, 2011
1622 ),
1623 ));
1624
1625 .. note::
1626
1627 If you use a form login, Symfony2 will create a cookie even if you set
1628 ``stateless`` to ``true``.
1629
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
1630 Final Words
1631 -----------
1632
1633 Security can be a deep and complex issue to solve correctly in your application.
1634 Fortunately, Symfony's security component follows a well-proven security
1635 model based around *authentication* and *authorization*. Authentication,
1636 which always happens first, is handled by a firewall whose job is to determine
1637 the identity of the user through several different methods (e.g. HTTP authentication,
1638 login form, etc). In the cookbook, you'll find examples of other methods
1639 for handling authentication, including how to implement a "remember me" cookie
1640 functionality.
1641
1642 Once a user is authenticated, the authorization layer can determine whether
1643 or not the user should have access to a specific resource. Most commonly,
1644 *roles* are applied to URLs, classes or methods and if the current user
1645 doesn't have that role, access is denied. The authorization layer, however,
1646 is much deeper, and follows a system of "voting" so that multiple parties
1647 can determine if the current user should have access to a given resource.
1648 Find out more about this and other topics in the cookbook.
1649
1650 Learn more from the Cookbook
1651 ----------------------------
1652
1653 * :doc:`Forcing HTTP/HTTPS </cookbook/security/force_https>`
1654 * :doc:`Blacklist users by IP address with a custom voter </cookbook/security/voters>`
1655 * :doc:`Access Control Lists (ACLs) </cookbook/security/acl>`
4ab14ef @weaverryan [book][security] More chapter proofreading, adding another stub chapter
weaverryan authored May 14, 2011
1656 * :doc:`/cookbook/security/remember_me`
55dbee2 @weaverryan [book][security] WIP security proofreading
weaverryan authored May 13, 2011
1657
38b80e9 @weaverryan [Security] WIP refactoring of the security chapter
weaverryan authored May 8, 2011
1658 .. _`security component`: https://github.com/symfony/Security
1659 .. _`SecurityExtraBundle`: https://github.com/schmittjoh/SecurityExtraBundle
49e39db @weaverryan [book][security] Other changes per @stof
weaverryan authored May 12, 2011
1660 .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/UserBundle
d528149 @schmittjoh updated to recommend \Serializable
schmittjoh authored Jun 1, 2011
1661 .. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php
42214df @weaverryan [book][security] Adding details on hashing passwords and using access…
weaverryan authored May 11, 2011
1662 .. _`functions-online.com`: http://www.functions-online.com/sha1.html
Something went wrong with that request. Please try again.