Skip to content

Commit dba4edf

Browse files
author
Iltar van der Berg
committed
Updated documentation regarding the SecurityContext split.
1 parent 928a579 commit dba4edf

File tree

13 files changed

+142
-99
lines changed

13 files changed

+142
-99
lines changed

book/security.rst

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ Next, create the controller that will display the login form::
438438

439439
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
440440
use Symfony\Component\HttpFoundation\Request;
441-
use Symfony\Component\Security\Core\SecurityContextInterface;
441+
use Symfony\Component\Security\Core\SecuritySessionStorageInterface;
442442

443443
class SecurityController extends Controller
444444
{
@@ -447,19 +447,19 @@ Next, create the controller that will display the login form::
447447
$session = $request->getSession();
448448

449449
// get the login error if there is one
450-
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
450+
if ($request->attributes->has(SecuritySessionStorageInterface::AUTHENTICATION_ERROR)) {
451451
$error = $request->attributes->get(
452-
SecurityContextInterface::AUTHENTICATION_ERROR
452+
SecuritySessionStorageInterface::AUTHENTICATION_ERROR
453453
);
454-
} elseif (null !== $session && $session->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
455-
$error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR);
456-
$session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
454+
} elseif (null !== $session && $session->has(SecuritySessionStorageInterface::AUTHENTICATION_ERROR)) {
455+
$error = $session->get(SecuritySessionStorageInterface::AUTHENTICATION_ERROR);
456+
$session->remove(SecuritySessionStorageInterface::AUTHENTICATION_ERROR);
457457
} else {
458458
$error = '';
459459
}
460460

461461
// last username entered by the user
462-
$lastUsername = (null === $session) ? '' : $session->get(SecurityContextInterface::LAST_USERNAME);
462+
$lastUsername = (null === $session) ? '' : $session->get(SecuritySessionStorageInterface::LAST_USERNAME);
463463

464464
return $this->render(
465465
'AcmeSecurityBundle:Security:login.html.twig',
@@ -713,7 +713,7 @@ see :doc:`/cookbook/security/form_login`.
713713
``/login_check`` doesn't match any firewall, you'll receive a ``Unable
714714
to find the controller for path "/login_check"`` exception.
715715

716-
**4. Multiple firewalls don't share security context**
716+
**4. Multiple firewalls don't share the same context**
717717

718718
If you're using multiple firewalls and you authenticate against one firewall,
719719
you will *not* be authenticated against any other firewalls automatically.
@@ -1174,7 +1174,7 @@ authorization from inside a controller::
11741174

11751175
public function helloAction($name)
11761176
{
1177-
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
1177+
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
11781178
throw $this->createAccessDeniedException('Unable to access this page!');
11791179
}
11801180

@@ -1186,6 +1186,9 @@ authorization from inside a controller::
11861186
.. versionadded:: 2.5
11871187
The ``createAccessDeniedException`` method was introduced in Symfony 2.5.
11881188

1189+
.. versionadded:: 2.6
1190+
Service ``security.authorization_checker`` replaces ``security.context`` for ``isGranted`` as of 2.6.
1191+
11891192
The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException`
11901193
method creates a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`
11911194
object, which ultimately triggers a 403 HTTP response inside Symfony.
@@ -1595,14 +1598,17 @@ Retrieving the User Object
15951598
~~~~~~~~~~~~~~~~~~~~~~~~~~
15961599

15971600
After authentication, the ``User`` object of the current user can be accessed
1598-
via the ``security.context`` service. From inside a controller, this will
1601+
via the ``security.token_storage`` service. From inside a controller, this will
15991602
look like::
16001603

16011604
public function indexAction()
16021605
{
1603-
$user = $this->get('security.context')->getToken()->getUser();
1606+
$user = $this->get('security.token_storage')->getToken()->getUser();
16041607
}
16051608

1609+
.. versionadded:: 2.6
1610+
Service ``security.token_storage`` replaces ``security.context`` for ``getToken`` as of 2.6.
1611+
16061612
In a controller this can be shortcut to:
16071613

16081614
.. code-block:: php
@@ -1870,13 +1876,16 @@ authorization from inside a controller::
18701876

18711877
public function helloAction($name)
18721878
{
1873-
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
1879+
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
18741880
throw new AccessDeniedException();
18751881
}
18761882

18771883
// ...
18781884
}
18791885

1886+
.. versionadded:: 2.6
1887+
Service ``security.authorization_checker`` replaces ``security.context`` for ``isGranted`` as of 2.6.
1888+
18801889
.. caution::
18811890

18821891
A firewall must be active or an exception will be thrown when the ``isGranted()``
@@ -1900,7 +1909,7 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object::
19001909

19011910
public function indexAction()
19021911
{
1903-
if (!$this->get('security.context')->isGranted(new Expression(
1912+
if (!$this->get('security.authorization_checker')->isGranted(new Expression(
19041913
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
19051914
))) {
19061915
throw new AccessDeniedException();
@@ -1909,6 +1918,9 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object::
19091918
// ...
19101919
}
19111920

1921+
.. versionadded:: 2.6
1922+
Service ``security.authorization_checker`` replaces ``security.context`` for ``isGranted`` as of 2.6.
1923+
19121924
In this example, if the current user has ``ROLE_ADMIN`` or if the current
19131925
user object's ``isSuperAdmin()`` method returns ``true``, then access will
19141926
be granted (note: your User object may not have an ``isSuperAdmin`` method,
@@ -1954,10 +1966,10 @@ Additionally, you have access to a number of functions inside the expression:
19541966
use Symfony\Component\ExpressionLanguage\Expression;
19551967
// ...
19561968

1957-
$sc = $this->get('security.context');
1958-
$access1 = $sc->isGranted('IS_AUTHENTICATED_REMEMBERED');
1969+
$ac = $this->get('security.authorization_checker');
1970+
$access1 = $ac->isGranted('IS_AUTHENTICATED_REMEMBERED');
19591971

1960-
$access2 = $sc->isGranted(new Expression(
1972+
$access2 = $ac->isGranted(new Expression(
19611973
'is_remember_me() or is_fully_authenticated()'
19621974
));
19631975

book/templating.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,10 @@ automatically:
11551155
<p>Application Environment: <?php echo $app->getEnvironment() ?></p>
11561156
<?php endif; ?>
11571157

1158+
.. versionadded:: 2.6
1159+
The security context is deprecated as of 2.6 as the user is already available
1160+
as ``app.user`` and ``is_granted()`` is registered as function.
1161+
11581162
.. tip::
11591163

11601164
You can add your own global template variables. See the cookbook example

components/security/authentication.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@ firewall map is able to extract the user's credentials from the current
1010
a token, containing these credentials. The next thing the listener should
1111
do is ask the authentication manager to validate the given token, and return
1212
an *authenticated* token if the supplied credentials were found to be valid.
13-
The listener should then store the authenticated token in the security context::
13+
The listener should then store the authenticated token in the token storage::
1414

1515
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
16-
use Symfony\Component\Security\Core\SecurityContextInterface;
16+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
1717
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
1818
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
1919
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
2020

2121
class SomeAuthenticationListener implements ListenerInterface
2222
{
2323
/**
24-
* @var SecurityContextInterface
24+
* @var TokenStorageInterface
2525
*/
26-
private $securityContext;
26+
private $tokenStorage;
2727

2828
/**
2929
* @var AuthenticationManagerInterface
@@ -54,10 +54,13 @@ The listener should then store the authenticated token in the security context::
5454
->authenticationManager
5555
->authenticate($unauthenticatedToken);
5656

57-
$this->securityContext->setToken($authenticatedToken);
57+
$this->tokenStorage->setToken($authenticatedToken);
5858
}
5959
}
6060

61+
.. versionadded:: 2.6
62+
Class ``TokenStorage`` replaces ``SecurityContext`` for ``getToken`` as of 2.6.
63+
6164
.. note::
6265

6366
A token can be of any class, as long as it implements

components/security/authorization.rst

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ Authorization
77
When any of the authentication providers (see :ref:`authentication_providers`)
88
has verified the still-unauthenticated token, an authenticated token will
99
be returned. The authentication listener should set this token directly
10-
in the :class:`Symfony\\Component\\Security\\Core\\SecurityContextInterface`
11-
using its :method:`Symfony\\Component\\Security\\Core\\SecurityContextInterface::setToken`
10+
in the :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface`
11+
using its :method:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface::setToken`
1212
method.
1313

1414
From then on, the user is authenticated, i.e. identified. Now, other parts
@@ -227,23 +227,24 @@ are required for the current user to get access to the application::
227227
$authenticationManager
228228
);
229229

230-
Security Context
231-
~~~~~~~~~~~~~~~~
230+
Authorization Checker
231+
~~~~~~~~~~~~~~~~~~~~~
232232

233233
The access decision manager is also available to other parts of the application
234-
via the :method:`Symfony\\Component\\Security\\Core\\SecurityContext::isGranted`
235-
method of the :class:`Symfony\\Component\\Security\\Core\\SecurityContext`.
234+
via the :method:`Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker::isGranted`
235+
method of the :class:`Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker`.
236236
A call to this method will directly delegate the question to the access
237237
decision manager::
238238

239-
use Symfony\Component\Security\SecurityContext;
239+
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
240240
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
241241

242-
$securityContext = new SecurityContext(
242+
$authorizationChecker = new AuthorizationChecker(
243+
$tokenStorage,
243244
$authenticationManager,
244245
$accessDecisionManager
245246
);
246247

247-
if (!$securityContext->isGranted('ROLE_ADMIN')) {
248+
if (!$authorizationChecker->isGranted('ROLE_ADMIN')) {
248249
throw new AccessDeniedException();
249250
}

components/security/firewall.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ certain action or resource of the application::
3030
throw new AccessDeniedException();
3131
}
3232

33+
.. versionadded:: 2.6
34+
The ``SecurityContext`` is deprecated of 2.6 and is replaced by the ``AuthorizationChecker``
35+
and ``TokenStorage``.
36+
37+
3338
.. note::
3439

3540
Read the dedicated sections to learn more about :doc:`/components/security/authentication`
@@ -115,7 +120,7 @@ which will eventually result in an "HTTP/1.1 403: Access Denied" response.
115120
Entry Points
116121
~~~~~~~~~~~~
117122

118-
When the user is not authenticated at all (i.e. when the security context
123+
When the user is not authenticated at all (i.e. when the token storage
119124
has no token yet), the firewall's entry point will be called to "start"
120125
the authentication process. An entry point should implement
121126
:class:`Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface`,

cookbook/form/dynamic_form_modification.rst

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ Using an event listener, your form might look like this::
223223
use Symfony\Component\Form\FormBuilderInterface;
224224
use Symfony\Component\Form\FormEvents;
225225
use Symfony\Component\Form\FormEvent;
226-
use Symfony\Component\Security\Core\SecurityContext;
226+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
227227
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
228228

229229
class FriendMessageFormType extends AbstractType
@@ -255,17 +255,17 @@ contains only this user's friends.
255255
Luckily it is pretty easy to inject a service inside of the form. This can be
256256
done in the constructor::
257257

258-
private $securityContext;
258+
private $tokenStorage;
259259

260-
public function __construct(SecurityContext $securityContext)
260+
public function __construct(TokenStorageInterface $tokenStorage)
261261
{
262-
$this->securityContext = $securityContext;
262+
$this->tokenStorage = $tokenStorage;
263263
}
264264

265265
.. note::
266266

267-
You might wonder, now that you have access to the User (through the security
268-
context), why not just use it directly in ``buildForm`` and omit the
267+
You might wonder, now that you have access to the User (through the token
268+
storage), why not just use it directly in ``buildForm`` and omit the
269269
event listener? This is because doing so in the ``buildForm`` method
270270
would result in the whole form type being modified and not just this
271271
one form instance. This may not usually be a problem, but technically
@@ -275,22 +275,22 @@ done in the constructor::
275275
Customizing the Form Type
276276
~~~~~~~~~~~~~~~~~~~~~~~~~
277277

278-
Now that you have all the basics in place you can take advantage of the ``SecurityContext``
278+
Now that you have all the basics in place you can take advantage of the ``TokenStorageInterface``
279279
and fill in the listener logic::
280280

281281
// src/Acme/DemoBundle/FormType/FriendMessageFormType.php
282282

283-
use Symfony\Component\Security\Core\SecurityContext;
283+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
284284
use Doctrine\ORM\EntityRepository;
285285
// ...
286286

287287
class FriendMessageFormType extends AbstractType
288288
{
289-
private $securityContext;
289+
private $tokenStorage;
290290

291-
public function __construct(SecurityContext $securityContext)
291+
public function __construct(TokenStorageInterface $tokenStorage)
292292
{
293-
$this->securityContext = $securityContext;
293+
$this->tokenStorage = $tokenStorage;
294294
}
295295

296296
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -301,7 +301,7 @@ and fill in the listener logic::
301301
;
302302

303303
// grab the user, do a quick sanity check that one exists
304-
$user = $this->securityContext->getToken()->getUser();
304+
$user = $this->tokenStorage->getToken()->getUser();
305305
if (!$user) {
306306
throw new \LogicException(
307307
'The FriendMessageFormType cannot be used without an authenticated user!'
@@ -336,6 +336,9 @@ and fill in the listener logic::
336336
// ...
337337
}
338338

339+
.. versionadded:: 2.6
340+
``TokenStorageInterface`` replaces ``SecurityContext`` for ``getToken`` as of 2.6.
341+
339342
.. note::
340343

341344
The ``multiple`` and ``expanded`` form options will default to false
@@ -347,7 +350,7 @@ Using the Form
347350
Our form is now ready to use and there are two possible ways to use it inside
348351
of a controller:
349352

350-
a) create it manually and remember to pass the security context to it;
353+
a) create it manually and remember to pass the token storage to it;
351354

352355
or
353356

@@ -363,9 +366,9 @@ your new form type in many places or embedding it into other forms::
363366
{
364367
public function newAction(Request $request)
365368
{
366-
$securityContext = $this->container->get('security.context');
369+
$tokenStorage = $this->container->get('security.token_storage');
367370
$form = $this->createForm(
368-
new FriendMessageFormType($securityContext)
371+
new FriendMessageFormType($tokenStorage)
369372
);
370373

371374
// ...
@@ -386,7 +389,7 @@ it with :ref:`dic-tags-form-type`.
386389
services:
387390
acme.form.friend_message:
388391
class: Acme\DemoBundle\Form\Type\FriendMessageFormType
389-
arguments: ["@security.context"]
392+
arguments: ["@security.token_storage"]
390393
tags:
391394
- { name: form.type, alias: acme_friend_message }
392395
@@ -395,7 +398,7 @@ it with :ref:`dic-tags-form-type`.
395398
<!-- app/config/config.xml -->
396399
<services>
397400
<service id="acme.form.friend_message" class="Acme\DemoBundle\Form\Type\FriendMessageFormType">
398-
<argument type="service" id="security.context" />
401+
<argument type="service" id="security.token_storage" />
399402
<tag name="form.type" alias="acme_friend_message" />
400403
</service>
401404
</services>
@@ -408,7 +411,7 @@ it with :ref:`dic-tags-form-type`.
408411
$container->setDefinition(
409412
'acme.form.friend_message',
410413
$definition,
411-
array('security.context')
414+
array('security.token_storage')
412415
);
413416
414417
If you wish to create it from within a controller or any other service that has

0 commit comments

Comments
 (0)