Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dd1ca33

Browse filesBrowse files
committed
bug symfony#6495 Revert "minor symfony#6478 Replace reference to the "request" service (gerryvdm)" (WouterJ)
This PR was merged into the 2.7 branch. Discussion ---------- Revert "minor symfony#6478 Replace reference to the "request" service (gerryvdm)" This reverts commit 139e2e7, reversing changes made to 351f796. Similair to symfony#6490 but then for 2.7 Commits ------- 8da5a30 Revert "minor symfony#6478 Replace reference to the "request" service (gerryvdm)"
2 parents f5bcba6 + 8da5a30 commit dd1ca33
Copy full SHA for dd1ca33

File tree

Expand file treeCollapse file tree

135 files changed

+9915
-1811
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

135 files changed

+9915
-1811
lines changed

‎best_practices/forms.rst

Copy file name to clipboardExpand all lines: best_practices/forms.rst
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ form in its own PHP class::
2121

2222
use Symfony\Component\Form\AbstractType;
2323
use Symfony\Component\Form\FormBuilderInterface;
24-
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
24+
use Symfony\Component\OptionsResolver\OptionsResolver;
2525

2626
class PostType extends AbstractType
2727
{
@@ -36,7 +36,7 @@ form in its own PHP class::
3636
;
3737
}
3838

39-
public function setDefaultOptions(OptionsResolverInterface $resolver)
39+
public function configureOptions(OptionsResolver $resolver)
4040
{
4141
$resolver->setDefaults(array(
4242
'data_class' => 'AppBundle\Entity\Post'

‎best_practices/security.rst

Copy file name to clipboardExpand all lines: best_practices/security.rst
+159-17Lines changed: 159 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,16 @@ Authorization (i.e. Denying Access)
7474
-----------------------------------
7575

7676
Symfony gives you several ways to enforce authorization, including the ``access_control``
77-
configuration in :doc:`security.yml </reference/configuration/security>` and
78-
using :ref:`isGranted <best-practices-directly-isGranted>` on the ``security.context``
77+
configuration in :doc:`security.yml </reference/configuration/security>`, the
78+
:ref:`@Security annotation <best-practices-security-annotation>` and using
79+
:ref:`isGranted <best-practices-directly-isGranted>` on the ``security.authorization_checker``
7980
service directly.
8081

8182
.. best-practice::
8283

8384
* For protecting broad URL patterns, use ``access_control``;
84-
* Check security directly on the ``security.context`` service whenever
85+
* Whenever possible, use the ``@Security`` annotation;
86+
* Check security directly on the ``security.authorization_checker`` service whenever
8587
you have a more complex situation.
8688

8789
There are also different ways to centralize your authorization logic, like
@@ -93,21 +95,132 @@ with a custom security voter or with ACL.
9395
* For restricting access to *any* object by *any* user via an admin
9496
interface, use the Symfony ACL.
9597

96-
.. _best-practices-directly-isGranted:
97-
.. _checking-permissions-without-security:
98+
.. _best-practices-security-annotation:
99+
100+
The @Security Annotation
101+
------------------------
98102

99-
Manually Checking Permissions
100-
-----------------------------
103+
For controlling access on a controller-by-controller basis, use the ``@Security``
104+
annotation whenever possible. It's easy to read and is placed consistently
105+
above each action.
101106

102-
If you cannot control the access based on URL patterns, you can always do
103-
the security checks in PHP:
107+
In our application, you need the ``ROLE_ADMIN`` in order to create a new post.
108+
Using ``@Security``, this looks like:
104109

105110
.. code-block:: php
106111
107-
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
112+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
113+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
114+
// ...
115+
116+
/**
117+
* Displays a form to create a new Post entity.
118+
*
119+
* @Route("/new", name="admin_post_new")
120+
* @Security("has_role('ROLE_ADMIN')")
121+
*/
122+
public function newAction()
123+
{
124+
// ...
125+
}
126+
127+
Using Expressions for Complex Security Restrictions
128+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
129+
130+
If your security logic is a little bit more complex, you can use an `expression`_
131+
inside ``@Security``. In the following example, a user can only access the
132+
controller if their email matches the value returned by the ``getAuthorEmail``
133+
method on the ``Post`` object:
134+
135+
.. code-block:: php
136+
137+
use AppBundle\Entity\Post;
138+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
139+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
140+
141+
/**
142+
* @Route("/{id}/edit", name="admin_post_edit")
143+
* @Security("user.getEmail() == post.getAuthorEmail()")
144+
*/
145+
public function editAction(Post $post)
146+
{
147+
// ...
148+
}
149+
150+
Notice that this requires the use of the `ParamConverter`_, which automatically
151+
queries for the ``Post`` object and puts it on the ``$post`` argument. This
152+
is what makes it possible to use the ``post`` variable in the expression.
153+
154+
This has one major drawback: an expression in an annotation cannot easily
155+
be reused in other parts of the application. Imagine that you want to add
156+
a link in a template that will only be seen by authors. Right now you'll
157+
need to repeat the expression code using Twig syntax:
158+
159+
.. code-block:: html+jinja
160+
161+
{% if app.user and app.user.email == post.authorEmail %}
162+
<a href=""> ... </a>
163+
{% endif %}
108164

165+
The easiest solution - if your logic is simple enough - is to add a new method
166+
to the ``Post`` entity that checks if a given user is its author:
167+
168+
.. code-block:: php
169+
170+
// src/AppBundle/Entity/Post.php
109171
// ...
110172
173+
class Post
174+
{
175+
// ...
176+
177+
/**
178+
* Is the given User the author of this Post?
179+
*
180+
* @return bool
181+
*/
182+
public function isAuthor(User $user = null)
183+
{
184+
return $user && $user->getEmail() == $this->getAuthorEmail();
185+
}
186+
}
187+
188+
Now you can reuse this method both in the template and in the security expression:
189+
190+
.. code-block:: php
191+
192+
use AppBundle\Entity\Post;
193+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
194+
195+
/**
196+
* @Route("/{id}/edit", name="admin_post_edit")
197+
* @Security("post.isAuthor(user)")
198+
*/
199+
public function editAction(Post $post)
200+
{
201+
// ...
202+
}
203+
204+
.. code-block:: html+jinja
205+
206+
{% if post.isAuthor(app.user) %}
207+
<a href=""> ... </a>
208+
{% endif %}
209+
210+
.. _best-practices-directly-isGranted:
211+
.. _checking-permissions-without-security:
212+
.. _manually-checking-permissions:
213+
214+
Checking Permissions without @Security
215+
--------------------------------------
216+
217+
The above example with ``@Security`` only works because we're using the
218+
:ref:`ParamConverter <best-practices-paramconverter>`, which gives the expression
219+
access to the a ``post`` variable. If you don't use this, or have some other
220+
more advanced use-case, you can always do the same security check in PHP:
221+
222+
.. code-block:: php
223+
111224
/**
112225
* @Route("/{id}/edit", name="admin_post_edit")
113226
*/
@@ -121,7 +234,16 @@ the security checks in PHP:
121234
}
122235
123236
if (!$post->isAuthor($this->getUser())) {
124-
throw new AccessDeniedException();
237+
$this->denyAccessUnlessGranted('edit', $post);
238+
239+
// or without the shortcut:
240+
//
241+
// use Symfony\Component\Security\Core\Exception\AccessDeniedException;
242+
// ...
243+
//
244+
// if (!$this->get('security.authorization_checker')->isGranted('edit', $post)) {
245+
// throw $this->createAccessDeniedException();
246+
// }
125247
}
126248
127249
// ...
@@ -192,13 +314,23 @@ To enable the security voter in the application, define a new service:
192314
tags:
193315
- { name: security.voter }
194316
195-
Now, you can use the voter with the ``security.context`` service:
317+
Now, you can use the voter with the ``@Security`` annotation:
196318

197319
.. code-block:: php
198320
199-
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
321+
/**
322+
* @Route("/{id}/edit", name="admin_post_edit")
323+
* @Security("is_granted('edit', post)")
324+
*/
325+
public function editAction(Post $post)
326+
{
327+
// ...
328+
}
200329
201-
// ...
330+
You can also use this directly with the ``security.authorization_checker`` service or
331+
via the even easier shortcut in a controller:
332+
333+
.. code-block:: php
202334
203335
/**
204336
* @Route("/{id}/edit", name="admin_post_edit")
@@ -207,9 +339,16 @@ Now, you can use the voter with the ``security.context`` service:
207339
{
208340
$post = // query for the post ...
209341
210-
if (!$this->get('security.context')->isGranted('edit', $post)) {
211-
throw new AccessDeniedException();
212-
}
342+
$this->denyAccessUnlessGranted('edit', $post);
343+
344+
// or without the shortcut:
345+
//
346+
// use Symfony\Component\Security\Core\Exception\AccessDeniedException;
347+
// ...
348+
//
349+
// if (!$this->get('security.authorization_checker')->isGranted('edit', $post)) {
350+
// throw $this->createAccessDeniedException();
351+
// }
213352
}
214353
215354
Learn More
@@ -230,4 +369,7 @@ If your company uses a user login method not supported by Symfony, you can
230369
develop :doc:`your own user provider </cookbook/security/custom_provider>` and
231370
:doc:`your own authentication provider </cookbook/security/custom_authentication_provider>`.
232371

372+
.. _`ParamConverter`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
373+
.. _`@Security annotation`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html
374+
.. _`expression`: http://symfony.com/doc/current/components/expression_language/introduction.html
233375
.. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle

‎book/controller.rst

Copy file name to clipboardExpand all lines: book/controller.rst
+47-28Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -421,22 +421,26 @@ method is just a helper method that generates the URL for a given route.
421421
Redirecting
422422
~~~~~~~~~~~
423423

424-
To redirect the user's browser to another page of your app, use the ``generateUrl()``
425-
method in combination with another helper method called
426-
:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::redirect`
427-
which takes a URL as an argument::
424+
If you want to redirect the user to another page, use the ``redirectToRoute()`` method::
428425

429426
public function indexAction()
430427
{
431-
return $this->redirect($this->generateUrl('homepage'));
428+
return $this->redirectToRoute('homepage');
429+
430+
// redirectToRoute is equivalent to using redirect() and generateUrl() together:
431+
// return $this->redirect($this->generateUrl('homepage'));
432432
}
433433

434-
By default, the ``redirect()`` method performs a 302 (temporary) redirect. To
435-
perform a 301 (permanent) redirect, modify the second argument::
434+
.. versionadded:: 2.6
435+
The ``redirectToRoute()`` method was introduced in Symfony 2.6. Previously (and still now), you
436+
could use ``redirect()`` and ``generateUrl()`` together for this (see the example above).
437+
438+
By default, the ``redirectToRoute()`` method performs a 302 (temporary) redirect. To
439+
perform a 301 (permanent) redirect, modify the third argument::
436440

437441
public function indexAction()
438442
{
439-
return $this->redirect($this->generateUrl('homepage'), 301);
443+
return $this->redirectToRoute('homepage', array(), 301);
440444
}
441445

442446
To redirect to an *external* site, use ``redirect()`` and pass it the external URL::
@@ -450,12 +454,16 @@ For more information, see the :doc:`Routing chapter </book/routing>`.
450454

451455
.. tip::
452456

453-
The ``redirect()`` method is simply a shortcut that creates a ``Response``
454-
object that specializes in redirecting the user. It's equivalent to::
457+
The ``redirectToRoute()`` method is simply a shortcut that creates a
458+
``Response`` object that specializes in redirecting the user. It's
459+
equivalent to::
455460

456461
use Symfony\Component\HttpFoundation\RedirectResponse;
457462

458-
return new RedirectResponse($this->generateUrl('homepage'));
463+
public function indexAction()
464+
{
465+
return new RedirectResponse($this->generateUrl('homepage'));
466+
}
459467

460468
.. index::
461469
single: Controller; Rendering templates
@@ -520,12 +528,15 @@ need::
520528

521529
$mailer = $this->get('mailer');
522530

523-
What other services exist? To list all services, use the ``container:debug``
531+
What other services exist? To list all services, use the ``debug:container``
524532
console command:
525533

526534
.. code-block:: bash
527535
528-
$ php app/console container:debug
536+
$ php app/console debug:container
537+
538+
.. versionadded:: 2.6
539+
Prior to Symfony 2.6, this command was called ``container:debug``.
529540

530541
For more information, see the :doc:`/book/service_container` chapter.
531542

@@ -649,12 +660,14 @@ For example, imagine you're processing a form submission::
649660
if ($form->isValid()) {
650661
// do some sort of processing
651662

652-
$request->getSession()->getFlashBag()->add(
663+
$this->addFlash(
653664
'notice',
654665
'Your changes were saved!'
655666
);
656667

657-
return $this->redirect($this->generateUrl(...));
668+
// $this->addFlash is equivalent to $this->get('session')->getFlashBag()->add
669+
670+
return $this->redirectToRoute(...);
658671
}
659672

660673
return $this->render(...);
@@ -750,7 +763,7 @@ headers and content that's sent back to the client::
750763
use Symfony\Component\HttpFoundation\Response;
751764

752765
// create a simple Response with a 200 status code (the default)
753-
$response = new Response('Hello '.$name, 200);
766+
$response = new Response('Hello '.$name, Response::HTTP_OK);
754767

755768
// create a JSON-response with a 200 status code
756769
$response = new Response(json_encode(array('name' => $name)));
@@ -816,24 +829,30 @@ The target controller method might look something like this::
816829
Just like when creating a controller for a route, the order of the arguments of
817830
``fancyAction()`` doesn't matter: the matching is done by name.
818831

819-
Checking the Validity of a CSRF Token inside Controller
820-
-------------------------------------------------------
832+
.. _checking-the-validity-of-a-csrf-token:
821833

822-
You may sometimes want to use :ref:`CSRF protection <forms-csrf>` in a controller where
823-
you don't have a Symfony form.
834+
Validating a CSRF Token
835+
-----------------------
824836

825-
If, for example, you're doing a DELETE action, you can use the
826-
:method:`Symfony\\Component\\Form\\Extension\\Csrf\\CsrfProvider\\CsrfProviderInterface::isCsrfTokenValid`
837+
Sometimes, you want to use CSRF protection in an action where you don't want to
838+
use the Symfony Form component. If, for example, you're doing a DELETE action,
839+
you can use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::isCsrfTokenValid`
827840
method to check the CSRF token::
828841

829-
$csrf = $this->container->get('form.csrf_provider');
842+
if ($this->isCsrfTokenValid('token_id', $submittedToken)) {
843+
// ... do something, like deleting an object
844+
}
830845

831-
$intention = 'authenticate';
832-
$token = $csrf->generateCsrfToken($intention);
846+
.. versionadded:: 2.6
847+
The ``isCsrfTokenValid()`` shortcut method was introduced in Symfony 2.6.
848+
It is equivalent to executing the following code:
833849

834-
if (!$csrf->isCsrfTokenValid($intention, $token)) {
835-
// CSRF token invalid! Do something, like redirect with an error.
836-
}
850+
.. code-block:: php
851+
852+
use Symfony\Component\Security\Csrf\CsrfToken;
853+
854+
$this->get('security.csrf.token_manager')
855+
->isTokenValid(new CsrfToken('token_id', 'TOKEN'));
837856
838857
Final Thoughts
839858
--------------

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.