Skip to content

Commit 282870f

Browse files
author
Iltar van der Berg
committed
Updated documentation regarding the SecurityContext split; symfony/symfony#11690
1 parent 2962e14 commit 282870f

14 files changed

+160
-99
lines changed

book/security.rst

Lines changed: 32 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,10 @@ 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+
The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior
1191+
to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service.
1192+
11891193
The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException`
11901194
method creates a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`
11911195
object, which ultimately triggers a 403 HTTP response inside Symfony.
@@ -1622,14 +1626,18 @@ Retrieving the User Object
16221626
~~~~~~~~~~~~~~~~~~~~~~~~~~
16231627

16241628
After authentication, the ``User`` object of the current user can be accessed
1625-
via the ``security.context`` service. From inside a controller, this will
1629+
via the ``security.token_storage`` service. From inside a controller, this will
16261630
look like::
16271631

16281632
public function indexAction()
16291633
{
1630-
$user = $this->get('security.context')->getToken()->getUser();
1634+
$user = $this->get('security.token_storage')->getToken()->getUser();
16311635
}
16321636

1637+
.. versionadded:: 2.6
1638+
The ``security.token_storage`` service was introduced in Symfony 2.6. Prior
1639+
to Symfony 2.6, you had to use the ``getToken()`` method of the ``security.context`` service.
1640+
16331641
In a controller this can be shortcut to:
16341642

16351643
.. code-block:: php
@@ -1899,13 +1907,17 @@ authorization from inside a controller::
18991907

19001908
public function helloAction($name)
19011909
{
1902-
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
1910+
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
19031911
throw new AccessDeniedException();
19041912
}
19051913

19061914
// ...
19071915
}
19081916

1917+
.. versionadded:: 2.6
1918+
The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior
1919+
to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service.
1920+
19091921
.. caution::
19101922

19111923
A firewall must be active or an exception will be thrown when the ``isGranted()``
@@ -1929,7 +1941,7 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object::
19291941

19301942
public function indexAction()
19311943
{
1932-
if (!$this->get('security.context')->isGranted(new Expression(
1944+
if (!$this->get('security.authorization_checker')->isGranted(new Expression(
19331945
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
19341946
))) {
19351947
throw new AccessDeniedException();
@@ -1938,6 +1950,10 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object::
19381950
// ...
19391951
}
19401952

1953+
.. versionadded:: 2.6
1954+
The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior
1955+
to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service.
1956+
19411957
In this example, if the current user has ``ROLE_ADMIN`` or if the current
19421958
user object's ``isSuperAdmin()`` method returns ``true``, then access will
19431959
be granted (note: your User object may not have an ``isSuperAdmin`` method,
@@ -1983,10 +1999,10 @@ Additionally, you have access to a number of functions inside the expression:
19831999
use Symfony\Component\ExpressionLanguage\Expression;
19842000
// ...
19852001

1986-
$sc = $this->get('security.context');
1987-
$access1 = $sc->isGranted('IS_AUTHENTICATED_REMEMBERED');
2002+
$authorizationChecker = $this->get('security.authorization_checker');
2003+
$access1 = $authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED');
19882004

1989-
$access2 = $sc->isGranted(new Expression(
2005+
$access2 = $authorizationChecker->isGranted(new Expression(
19902006
'is_remember_me() or is_fully_authenticated()'
19912007
));
19922008

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 ``app.security`` (or ``$app->getSecurity()``) global is deprecated as of Symfony 2.6.
1160+
Use `app.user` (`$app->getUser()`) and `is_granted()` (`$view['security']->isGranted()`) instead.
1161+
11581162
.. tip::
11591163

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

components/security/authentication.rst

Lines changed: 10 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 using 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,15 @@ 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+
The :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface` was
63+
introduced in Symfony 2.6. Prior, you had to use the ``getToken()`` method of
64+
:class:`Symfony\\Component\\Security\\Core\\SecurityContextInterface`.
65+
6166
.. note::
6267

6368
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+
As of Symfony 2.6, the :class:`Symfony\\Component\\Security\\Core\\SecurityContext` class was split
35+
in the :class:`Symfony\\Component\\Security\\Core\\Authentication\\Authorization\\AuthorizationChecker` and
36+
:class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage` classes.
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: 23 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,11 @@ and fill in the listener logic::
336336
// ...
337337
}
338338

339+
.. versionadded:: 2.6
340+
The :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface` was
341+
introduced in Symfony 2.6. Prior, you had to use the ``getToken()`` method of
342+
:class:`Symfony\\Component\\Security\\Core\\SecurityContextInterface`.
343+
339344
.. note::
340345

341346
The ``multiple`` and ``expanded`` form options will default to false
@@ -347,7 +352,7 @@ Using the Form
347352
Our form is now ready to use and there are two possible ways to use it inside
348353
of a controller:
349354

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

352357
or
353358

@@ -363,9 +368,9 @@ your new form type in many places or embedding it into other forms::
363368
{
364369
public function newAction(Request $request)
365370
{
366-
$securityContext = $this->container->get('security.context');
371+
$tokenStorage = $this->container->get('security.token_storage');
367372
$form = $this->createForm(
368-
new FriendMessageFormType($securityContext)
373+
new FriendMessageFormType($tokenStorage)
369374
);
370375

371376
// ...
@@ -386,7 +391,7 @@ it with :ref:`dic-tags-form-type`.
386391
services:
387392
acme.form.friend_message:
388393
class: Acme\DemoBundle\Form\Type\FriendMessageFormType
389-
arguments: ["@security.context"]
394+
arguments: ["@security.token_storage"]
390395
tags:
391396
- { name: form.type, alias: acme_friend_message }
392397
@@ -395,7 +400,7 @@ it with :ref:`dic-tags-form-type`.
395400
<!-- app/config/config.xml -->
396401
<services>
397402
<service id="acme.form.friend_message" class="Acme\DemoBundle\Form\Type\FriendMessageFormType">
398-
<argument type="service" id="security.context" />
403+
<argument type="service" id="security.token_storage" />
399404
<tag name="form.type" alias="acme_friend_message" />
400405
</service>
401406
</services>
@@ -408,7 +413,7 @@ it with :ref:`dic-tags-form-type`.
408413
$container->setDefinition(
409414
'acme.form.friend_message',
410415
$definition,
411-
array('security.context')
416+
array('security.token_storage')
412417
);
413418
414419
If you wish to create it from within a controller or any other service that has

0 commit comments

Comments
 (0)