From 3bcb18653796fced2bdaa62aa7eb21b7d2e0a7b7 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Fri, 8 Aug 2014 16:33:04 +0200 Subject: [PATCH 1/9] Added shortcut methods for controllers --- book/controller.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index e79af5c803c..875446a242c 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -459,6 +459,10 @@ perform a 301 (permanent) redirect, modify the second argument:: return new RedirectResponse($this->generateUrl('homepage')); + You can also directly use ``redirectToRoute()`` and give it directly the route name like : + + return $this->redirectToRoute('homepage'); + .. index:: single: Controller; Rendering templates @@ -638,8 +642,13 @@ After processing the request, the controller sets a ``notice`` flash message in the session and then redirects. The name (``notice``) isn't significant - it's just something you invent and reference next. -In the template of the next page (or even better, in your base layout template), -the following code will render the ``notice`` message: +.. tip:: + + You can use the ``addFlash()`` method as a shortcut to + ``$this->get('session')->getFlashBag()->add()``. + +In the template of the next action, the following code could be used to render +the ``notice`` message: .. configuration-block:: From 4611ce9742b445ee8ad9d4e86f2f08947e1bba95 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Fri, 8 Aug 2014 17:12:43 +0200 Subject: [PATCH 2/9] Minor format improvements --- book/controller.rst | 12 +++++++----- book/security.rst | 21 +++++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 875446a242c..5adfa4502c0 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -459,7 +459,10 @@ perform a 301 (permanent) redirect, modify the second argument:: return new RedirectResponse($this->generateUrl('homepage')); - You can also directly use ``redirectToRoute()`` and give it directly the route name like : +.. versionadded:: 2.6 + You can also directly use + :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::redirectToRoute`` + and give it directly the route name like : return $this->redirectToRoute('homepage'); @@ -642,10 +645,9 @@ After processing the request, the controller sets a ``notice`` flash message in the session and then redirects. The name (``notice``) isn't significant - it's just something you invent and reference next. -.. tip:: - - You can use the ``addFlash()`` method as a shortcut to - ``$this->get('session')->getFlashBag()->add()``. +.. versionadded:: 2.6 + You can use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::addFlash`` + method as a shortcut to ``$this->get('session')->getFlashBag()->add(...)``. In the template of the next action, the following code could be used to render the ``notice`` message: diff --git a/book/security.rst b/book/security.rst index cb383cfa7d9..23070a4e726 100644 --- a/book/security.rst +++ b/book/security.rst @@ -804,6 +804,17 @@ the ``^``) would match ``/admin/foo`` but would also match URLs like ``/foo/admi .. _`book-security-securing-controller`: + +Securing other Services +~~~~~~~~~~~~~~~~~~~~~~~ + +In fact, anything in Symfony can be protected using a strategy similar to +the one seen in the previous section. For example, suppose you have a service +(i.e. a PHP class) whose job is to send emails from one user to another. +You can restrict use of this class - no matter where it's being used from - +to users that have a specific role. +>>>>>>> Minor format improvements + Securing Controllers and other Code ................................... @@ -813,8 +824,8 @@ You can easily deny access from inside a controller:: public function helloAction($name) { - if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { - throw $this->createAccessDeniedException(); + if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { + throw $this->createAccessDeniedException('Unable to access this page!'); } // ... @@ -831,6 +842,12 @@ The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAcc method creates a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` object, which ultimately triggers a 403 HTTP response inside Symfony. +.. versionadded:: 2.6 + You can use directly `$this->isGranted($role)` instead of + `$this->get('security.context')->isGranted($role)` to check if + a role is granted and `denyAccessUnlessGranted` to throw an exception + if the access is not granted (like in the example above). + That's it! If the user isn't logged in yet, they will be asked to login (e.g. redirected to the login page). If they *are* logged in, they'll be shown the 403 access denied page (which you can :ref:`customize `). From 7ae62e82227b7b524607a5450ea33b72a73d5124 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Fri, 8 Aug 2014 17:15:55 +0200 Subject: [PATCH 3/9] Minor improvements --- book/controller.rst | 4 ++-- book/security.rst | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 5adfa4502c0..0bff6722fdd 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -461,7 +461,7 @@ perform a 301 (permanent) redirect, modify the second argument:: .. versionadded:: 2.6 You can also directly use - :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::redirectToRoute`` + :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::redirectToRoute` and give it directly the route name like : return $this->redirectToRoute('homepage'); @@ -646,7 +646,7 @@ in the session and then redirects. The name (``notice``) isn't significant - it's just something you invent and reference next. .. versionadded:: 2.6 - You can use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::addFlash`` + You can use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::addFlash` method as a shortcut to ``$this->get('session')->getFlashBag()->add(...)``. In the template of the next action, the following code could be used to render diff --git a/book/security.rst b/book/security.rst index 23070a4e726..8ac043aea51 100644 --- a/book/security.rst +++ b/book/security.rst @@ -802,9 +802,6 @@ the ``^``) would match ``/admin/foo`` but would also match URLs like ``/foo/admi To learn about all of this, see :doc:`/cookbook/security/access_control`. -.. _`book-security-securing-controller`: - - Securing other Services ~~~~~~~~~~~~~~~~~~~~~~~ @@ -813,11 +810,15 @@ the one seen in the previous section. For example, suppose you have a service (i.e. a PHP class) whose job is to send emails from one user to another. You can restrict use of this class - no matter where it's being used from - to users that have a specific role. ->>>>>>> Minor format improvements + +.. _`book-security-securing-controller`: Securing Controllers and other Code ................................... +Securing a Controller +~~~~~~~~~~~~~~~~~~~~~ + You can easily deny access from inside a controller:: // ... @@ -835,6 +836,12 @@ You can easily deny access from inside a controller:: The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. +.. versionadded:: 2.6 + You can use directly :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::isGranted` + instead of `$this->get('security.context')->isGranted($role)` to check if + a role is granted and :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::denyAccessUnlessGranted` + to throw an exception if the access is not granted (like in the example above). + .. versionadded:: 2.5 The ``createAccessDeniedException`` method was introduced in Symfony 2.5. From 643c458a039e28b3d0bec8d3c76cd5a7784eed80 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Tue, 30 Sep 2014 09:18:55 +0200 Subject: [PATCH 4/9] redirect changed to redirectToRoute --- book/controller.rst | 25 ++++++------------------- book/doctrine.rst | 2 +- book/forms.rst | 6 +++--- book/propel.rst | 2 +- book/validation.rst | 2 +- components/form/introduction.rst | 2 +- cookbook/doctrine/file_uploads.rst | 6 +++--- cookbook/doctrine/registration_form.rst | 2 +- cookbook/form/direct_submit.rst | 6 +++--- cookbook/form/form_collections.rst | 2 +- 10 files changed, 21 insertions(+), 34 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 0bff6722fdd..be705aad29a 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -429,43 +429,30 @@ A great way to see the core functionality in action is to look in the Redirecting ~~~~~~~~~~~ -If you want to redirect the user to another page, use the -:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::redirect` -method:: +If you want to redirect the user to another page, use the ``redirectToRoute()`` method:: public function indexAction() { - return $this->redirect($this->generateUrl('homepage')); + return $this->redirectToRoute('homepage'); } -The ``generateUrl()`` method is just a helper function that generates the URL -for a given route. For more information, see the :doc:`Routing ` -chapter. - -By default, the ``redirect()`` method performs a 302 (temporary) redirect. To +By default, the ``redirectToRoute()`` method performs a 302 (temporary) redirect. To perform a 301 (permanent) redirect, modify the second argument:: public function indexAction() { - return $this->redirect($this->generateUrl('homepage'), 301); + return $this->redirectToRoute('homepage', 301); } .. tip:: - The ``redirect()`` method is simply a shortcut that creates a ``Response`` + The ``redirectToRoute()`` method is simply a shortcut that creates a ``Response`` object that specializes in redirecting the user. It's equivalent to:: use Symfony\Component\HttpFoundation\RedirectResponse; return new RedirectResponse($this->generateUrl('homepage')); -.. versionadded:: 2.6 - You can also directly use - :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::redirectToRoute` - and give it directly the route name like : - - return $this->redirectToRoute('homepage'); - .. index:: single: Controller; Rendering templates @@ -635,7 +622,7 @@ For example, imagine you're processing a form submit:: 'Your changes were saved!' ); - return $this->redirect($this->generateUrl(...)); + return $this->redirectToRoute(...); } return $this->render(...); diff --git a/book/doctrine.rst b/book/doctrine.rst index e60ab0118fe..989e6df93eb 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -667,7 +667,7 @@ you have a route that maps a product id to an update action in a controller:: $product->setName('New product name!'); $em->flush(); - return $this->redirect($this->generateUrl('homepage')); + return $this->redirectToRoute('homepage'); } Updating an object involves just three steps: diff --git a/book/forms.rst b/book/forms.rst index 7bdfd2d991c..4eba6a4f60e 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -234,7 +234,7 @@ controller:: if ($form->isValid()) { // perform some action, such as saving the task to the database - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } // ... @@ -319,7 +319,7 @@ querying if the "Save and add" button was clicked:: ? 'task_new' : 'task_success'; - return $this->redirect($this->generateUrl($nextAction)); + return $this->redirectToRoute($nextAction); } .. index:: @@ -1233,7 +1233,7 @@ it after a form submission can be done when the form is valid:: $em->persist($task); $em->flush(); - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } If, for some reason, you don't have access to your original ``$task`` object, diff --git a/book/propel.rst b/book/propel.rst index 9ff589afb04..483fbfdaedb 100644 --- a/book/propel.rst +++ b/book/propel.rst @@ -234,7 +234,7 @@ have a route that maps a product id to an update action in a controller:: $product->setName('New product name!'); $product->save(); - return $this->redirect($this->generateUrl('homepage')); + return $this->redirectToRoute('homepage'); } Updating an object involves just three steps: diff --git a/book/validation.rst b/book/validation.rst index a7a6a3c1d75..fd4264d7a1d 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -231,7 +231,7 @@ workflow looks like the following from inside a controller:: if ($form->isValid()) { // the validation passed, do something with the $author object - return $this->redirect($this->generateUrl(...)); + return $this->redirectToRoute(...); } return $this->render('BlogBundle:Author:form.html.twig', array( diff --git a/components/form/introduction.rst b/components/form/introduction.rst index 7321a1029a1..2e4a6e891f9 100644 --- a/components/form/introduction.rst +++ b/components/form/introduction.rst @@ -587,7 +587,7 @@ method: // ... perform some action, such as saving the data to the database - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } // ... diff --git a/cookbook/doctrine/file_uploads.rst b/cookbook/doctrine/file_uploads.rst index ab52ae4c940..21910b7d2d2 100644 --- a/cookbook/doctrine/file_uploads.rst +++ b/cookbook/doctrine/file_uploads.rst @@ -244,7 +244,7 @@ The following controller shows you how to handle the entire process:: $em->persist($document); $em->flush(); - return $this->redirect($this->generateUrl(...)); + return $this->redirectToRoute(...); } return array('form' => $form->createView()); @@ -267,7 +267,7 @@ in a moment to handle the file upload:: $em->persist($document); $em->flush(); - return $this->redirect(...); + return $this->redirectToRoute(...); } The ``upload()`` method will take advantage of the :class:`Symfony\\Component\\HttpFoundation\\File\\UploadedFile` @@ -432,7 +432,7 @@ call to ``$document->upload()`` should be removed from the controller:: $em->persist($document); $em->flush(); - return $this->redirect(...); + return $this->redirectToRoute(...); } .. note:: diff --git a/cookbook/doctrine/registration_form.rst b/cookbook/doctrine/registration_form.rst index 4e4abbb5a05..b6849791212 100644 --- a/cookbook/doctrine/registration_form.rst +++ b/cookbook/doctrine/registration_form.rst @@ -287,7 +287,7 @@ the validation and saves the data into the database:: $em->persist($registration->getUser()); $em->flush(); - return $this->redirect(...); + return $this->redirectToRoute(...); } return $this->render( diff --git a/cookbook/form/direct_submit.rst b/cookbook/form/direct_submit.rst index 221f7f534d8..7166210319b 100644 --- a/cookbook/form/direct_submit.rst +++ b/cookbook/form/direct_submit.rst @@ -25,7 +25,7 @@ submissions:: if ($form->isValid()) { // perform some action... - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } return $this->render('AcmeTaskBundle:Default:new.html.twig', array( @@ -66,7 +66,7 @@ method, pass the submitted data directly to if ($form->isValid()) { // perform some action... - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } } @@ -111,7 +111,7 @@ a convenient shortcut to the previous example:: if ($form->isValid()) { // perform some action... - return $this->redirect($this->generateUrl('task_success')); + return $this->redirectToRoute('task_success'); } } diff --git a/cookbook/form/form_collections.rst b/cookbook/form/form_collections.rst index 638a1dc2f49..32ccbc263f6 100644 --- a/cookbook/form/form_collections.rst +++ b/cookbook/form/form_collections.rst @@ -717,7 +717,7 @@ the relationship between the removed ``Tag`` and ``Task`` object. $em->flush(); // redirect back to some edit page - return $this->redirect($this->generateUrl('task_edit', array('id' => $id))); + return $this->redirectToRoute('task_edit', array('id' => $id)); } // render some form template From 46e2505edbea59a80ae843477419738f07fb3119 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Tue, 30 Sep 2014 09:23:45 +0200 Subject: [PATCH 5/9] Changed to addFlash where it is possible (ie in controllers) --- book/controller.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index be705aad29a..746e9f6c5ec 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -617,7 +617,7 @@ For example, imagine you're processing a form submit:: if ($form->isValid()) { // do some sort of processing - $request->getSession()->getFlashBag()->add( + $this->addFlash( 'notice', 'Your changes were saved!' ); @@ -632,10 +632,6 @@ After processing the request, the controller sets a ``notice`` flash message in the session and then redirects. The name (``notice``) isn't significant - it's just something you invent and reference next. -.. versionadded:: 2.6 - You can use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::addFlash` - method as a shortcut to ``$this->get('session')->getFlashBag()->add(...)``. - In the template of the next action, the following code could be used to render the ``notice`` message: From 7f9bc8cdb7ff42443affe5029536285e58a8d2c3 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Tue, 30 Sep 2014 09:29:53 +0200 Subject: [PATCH 6/9] And now the same for isGranted where it is possible --- book/security.rst | 21 +++++---------------- cookbook/security/remember_me.rst | 10 +--------- cookbook/security/securing_services.rst | 8 +------- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/book/security.rst b/book/security.rst index 8ac043aea51..c945cb19299 100644 --- a/book/security.rst +++ b/book/security.rst @@ -816,32 +816,17 @@ to users that have a specific role. Securing Controllers and other Code ................................... -Securing a Controller -~~~~~~~~~~~~~~~~~~~~~ - You can easily deny access from inside a controller:: // ... public function helloAction($name) { - if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { - throw $this->createAccessDeniedException('Unable to access this page!'); - } + $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); // ... } -.. versionadded:: 2.6 - The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior - to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. - -.. versionadded:: 2.6 - You can use directly :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::isGranted` - instead of `$this->get('security.context')->isGranted($role)` to check if - a role is granted and :method:`Symfony\\Bundle\\FrameworkBundle\\Controller::denyAccessUnlessGranted` - to throw an exception if the access is not granted (like in the example above). - .. versionadded:: 2.5 The ``createAccessDeniedException`` method was introduced in Symfony 2.5. @@ -872,6 +857,10 @@ using annotations:: */ public function helloAction($name) { + $this->denyAccessUnlessGranted(new Expression( + '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' + )); + // ... } diff --git a/cookbook/security/remember_me.rst b/cookbook/security/remember_me.rst index 4a302a16c49..93987552e68 100644 --- a/cookbook/security/remember_me.rst +++ b/cookbook/security/remember_me.rst @@ -162,19 +162,11 @@ In the following example, the action is only allowed if the user has the public function editAction() { - if (false === $this->get('security.authorization_checker')->isGranted( - 'IS_AUTHENTICATED_FULLY' - )) { - throw new AccessDeniedException(); - } + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); // ... } -.. versionadded:: 2.6 - The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior - to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. - If your application is based on the Symfony Standard Edition, you can also secure your controller using annotations: diff --git a/cookbook/security/securing_services.rst b/cookbook/security/securing_services.rst index f877cffd125..fc33f05e083 100644 --- a/cookbook/security/securing_services.rst +++ b/cookbook/security/securing_services.rst @@ -14,17 +14,11 @@ and checking the current user's role:: public function helloAction($name) { - if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { - throw new AccessDeniedException(); - } + $this->denyAccessUnlessGranted('ROLE_ADMIN'); // ... } -.. versionadded:: 2.6 - The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior - to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service. - You can also secure *any* service in a similar way by injecting the ``security.authorization_checker`` service into it. For a general introduction to injecting dependencies into services see the :doc:`/book/service_container` chapter of the book. For From 5b015f2375e6e0b837049b587a3fe12232642522 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Sun, 4 Jan 2015 12:17:32 +0100 Subject: [PATCH 7/9] Modifications according to comments --- book/controller.rst | 18 +++++++++++++++++- book/security.rst | 29 ++++++++++++++++------------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 746e9f6c5ec..3bccb90ce6d 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -434,6 +434,20 @@ If you want to redirect the user to another page, use the ``redirectToRoute()`` public function indexAction() { return $this->redirectToRoute('homepage'); + + // redirectToRoute is equivalent to using redirect() and generateUrl() together: + // return $this->redirect($this->generateUrl('homepage'), 301); + } + +.. versionadded:: 2.6 + The ``redirectToRoute()`` method was added in Symfony 2.6. Previously (and still now), you + could use ``redirect()`` and ``generateUrl()`` together for this (see the example below). + +Or, if you want to redirect externally, just use ``redirect()`` and pass it the URL:: + + public function indexAction() + { + return $this->redirect('http://symfony.com/doc'); } By default, the ``redirectToRoute()`` method performs a 302 (temporary) redirect. To @@ -446,7 +460,7 @@ perform a 301 (permanent) redirect, modify the second argument:: .. tip:: - The ``redirectToRoute()`` method is simply a shortcut that creates a ``Response`` + The ``redirect()`` method is simply a shortcut that creates a ``Response`` object that specializes in redirecting the user. It's equivalent to:: use Symfony\Component\HttpFoundation\RedirectResponse; @@ -622,6 +636,8 @@ For example, imagine you're processing a form submit:: 'Your changes were saved!' ); + // $this->addFlash is equivalent to $this->get('session')->getFlashBag()->add + return $this->redirectToRoute(...); } diff --git a/book/security.rst b/book/security.rst index c945cb19299..cca1efebafb 100644 --- a/book/security.rst +++ b/book/security.rst @@ -816,7 +816,14 @@ to users that have a specific role. Securing Controllers and other Code ................................... -You can easily deny access from inside a controller:: +You can easily deny access from inside a controller: + +.. versionadded:: 2.6 + The ``denyAccessUnlessGranted()`` method was introduced in Symfony 2.6. Previously (and + still now), you could check access directly and throw the ``AccessDeniedException`` as shown + in the example below). + +.. code-block:: php // ... @@ -824,21 +831,17 @@ You can easily deny access from inside a controller:: { $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); + // Old way : + // if (false === $this->isGranted('ROLE_ADMIN')) { + // throw $this->createAccessDeniedException('Unable to access this page!'); + // } + // ... } -.. versionadded:: 2.5 - The ``createAccessDeniedException`` method was introduced in Symfony 2.5. - -The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException` -method creates a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` -object, which ultimately triggers a 403 HTTP response inside Symfony. - -.. versionadded:: 2.6 - You can use directly `$this->isGranted($role)` instead of - `$this->get('security.context')->isGranted($role)` to check if - a role is granted and `denyAccessUnlessGranted` to throw an exception - if the access is not granted (like in the example above). +In both cases, a special +:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` +is thrown, which ultimately triggers a 403 HTTP response inside Symfony. That's it! If the user isn't logged in yet, they will be asked to login (e.g. redirected to the login page). If they *are* logged in, they'll be shown From f807d14aaccf7e40d4f75fc73011696ffee67126 Mon Sep 17 00:00:00 2001 From: Thomas Royer Date: Sun, 4 Jan 2015 15:49:50 +0100 Subject: [PATCH 8/9] Fixes --- book/security.rst | 28 +++++++--------------------- cookbook/expression/expressions.rst | 6 ++---- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/book/security.rst b/book/security.rst index cca1efebafb..1316111bc27 100644 --- a/book/security.rst +++ b/book/security.rst @@ -802,33 +802,18 @@ the ``^``) would match ``/admin/foo`` but would also match URLs like ``/foo/admi To learn about all of this, see :doc:`/cookbook/security/access_control`. -Securing other Services -~~~~~~~~~~~~~~~~~~~~~~~ - -In fact, anything in Symfony can be protected using a strategy similar to -the one seen in the previous section. For example, suppose you have a service -(i.e. a PHP class) whose job is to send emails from one user to another. -You can restrict use of this class - no matter where it's being used from - -to users that have a specific role. - .. _`book-security-securing-controller`: Securing Controllers and other Code ................................... -You can easily deny access from inside a controller: - -.. versionadded:: 2.6 - The ``denyAccessUnlessGranted()`` method was introduced in Symfony 2.6. Previously (and - still now), you could check access directly and throw the ``AccessDeniedException`` as shown - in the example below). - -.. code-block:: php +You can easily deny access from inside a controller:: // ... public function helloAction($name) { + // The second parameter is used to specify on what object the role is tested. $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); // Old way : @@ -839,6 +824,11 @@ You can easily deny access from inside a controller: // ... } +.. versionadded:: 2.6 + The ``denyAccessUnlessGranted()`` method was introduced in Symfony 2.6. Previously (and + still now), you could check access directly and throw the ``AccessDeniedException`` as shown + in the example above). + In both cases, a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` is thrown, which ultimately triggers a 403 HTTP response inside Symfony. @@ -860,10 +850,6 @@ using annotations:: */ public function helloAction($name) { - $this->denyAccessUnlessGranted(new Expression( - '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' - )); - // ... } diff --git a/cookbook/expression/expressions.rst b/cookbook/expression/expressions.rst index 63fc728343c..73e43745bb8 100644 --- a/cookbook/expression/expressions.rst +++ b/cookbook/expression/expressions.rst @@ -33,11 +33,9 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object:: public function indexAction() { - if (!$this->get('security.authorization_checker')->isGranted(new Expression( + $this->denyAccessUnlessGranted(new Expression( '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' - ))) { - throw $this->createAccessDeniedException(); - } + )); // ... } From 994ed3a4ab0f19961a51bb992e4887a49e1e3cd2 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 10 Mar 2015 11:12:52 +0100 Subject: [PATCH 9/9] Little fixes --- book/controller.rst | 14 +++++++++----- book/security.rst | 2 +- cookbook/security/securing_services.rst | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 3bccb90ce6d..d424d8b4426 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -441,7 +441,7 @@ If you want to redirect the user to another page, use the ``redirectToRoute()`` .. versionadded:: 2.6 The ``redirectToRoute()`` method was added in Symfony 2.6. Previously (and still now), you - could use ``redirect()`` and ``generateUrl()`` together for this (see the example below). + could use ``redirect()`` and ``generateUrl()`` together for this (see the example above). Or, if you want to redirect externally, just use ``redirect()`` and pass it the URL:: @@ -455,17 +455,21 @@ perform a 301 (permanent) redirect, modify the second argument:: public function indexAction() { - return $this->redirectToRoute('homepage', 301); + return $this->redirectToRoute('homepage', array(), 301); } .. tip:: - The ``redirect()`` method is simply a shortcut that creates a ``Response`` - object that specializes in redirecting the user. It's equivalent to:: + The ``redirectToRoute()`` method is simply a shortcut that creates a + ``Response`` object that specializes in redirecting the user. It's + equivalent to:: use Symfony\Component\HttpFoundation\RedirectResponse; - return new RedirectResponse($this->generateUrl('homepage')); + public function indexAction() + { + return new RedirectResponse($this->generateUrl('homepage')); + } .. index:: single: Controller; Rendering templates diff --git a/book/security.rst b/book/security.rst index 1316111bc27..f96a277c256 100644 --- a/book/security.rst +++ b/book/security.rst @@ -817,7 +817,7 @@ You can easily deny access from inside a controller:: $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); // Old way : - // if (false === $this->isGranted('ROLE_ADMIN')) { + // if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { // throw $this->createAccessDeniedException('Unable to access this page!'); // } diff --git a/cookbook/security/securing_services.rst b/cookbook/security/securing_services.rst index fc33f05e083..0b37720654a 100644 --- a/cookbook/security/securing_services.rst +++ b/cookbook/security/securing_services.rst @@ -5,9 +5,10 @@ How to Secure any Service or Method in your Application ======================================================= -In the security chapter, you can see how to :ref:`secure a controller ` -by requesting the ``security.authorization_checker`` service from the Service Container -and checking the current user's role:: +In the security chapter, you can see how to +:ref:`secure a controller ` by requesting +the ``security.authorization_checker`` service from the Service Container and +checking the current user's role:: // ... use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -19,21 +20,19 @@ and checking the current user's role:: // ... } -You can also secure *any* service in a similar way by injecting the ``security.authorization_checker`` +You can also secure *any* service by injecting the ``security.authorization_checker`` service into it. For a general introduction to injecting dependencies into services see the :doc:`/book/service_container` chapter of the book. For example, suppose you have a ``NewsletterManager`` class that sends out emails -and you want to restrict its use to only users who have some ``ROLE_NEWSLETTER_ADMIN`` -role. Before you add security, the class looks something like this: - -.. code-block:: php +and you want to restrict its use to only users who have some +``ROLE_NEWSLETTER_ADMIN`` role. Before you add security, the class looks +something like this:: // src/AppBundle/Newsletter/NewsletterManager.php namespace AppBundle\Newsletter; class NewsletterManager { - public function sendNewsletter() { // ... where you actually do the work @@ -49,8 +48,9 @@ check, this is an ideal candidate for constructor injection, which guarantees that the authorization checker object will be available inside the ``NewsletterManager`` class:: - namespace AppBundle\Newsletter; + // src/AppBundle/Newsletter/NewsletterManager.php + // ... use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class NewsletterManager