Переглянути джерело

[Security] Refactored security context, moved getUser() implementation to templating

Johannes Schmitt 14 роки тому
батько
коміт
19bbafc441
18 змінених файлів з 100 додано та 77 видалено
  1. 3 3
      src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
  2. 8 3
      src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php
  3. 8 3
      src/Symfony/Bundle/SecurityBundle/Twig/Extension/SecurityExtension.php
  4. 13 3
      src/Symfony/Bundle/TwigBundle/GlobalVariables.php
  5. 1 3
      src/Symfony/Component/Security/Core/Authentication/Token/Token.php
  6. 8 22
      src/Symfony/Component/Security/Core/SecurityContext.php
  7. 21 0
      src/Symfony/Component/Security/Core/SecurityContextInterface.php
  8. 0 1
      src/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php
  9. 3 3
      src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php
  10. 2 2
      src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php
  11. 3 3
      src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php
  12. 2 2
      src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php
  13. 2 2
      src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php
  14. 2 2
      src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php
  15. 3 3
      src/Symfony/Component/Security/Http/Firewall/LogoutListener.php
  16. 2 2
      src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
  17. 2 2
      src/Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php
  18. 17 18
      tests/Symfony/Tests/Component/Security/Core/SecurityContextTest.php

+ 3 - 3
src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php

@@ -11,7 +11,7 @@
 
 namespace Symfony\Bundle\SecurityBundle\DataCollector;
 
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\DataCollector\DataCollector;
@@ -25,7 +25,7 @@ class SecurityDataCollector extends DataCollector
 {
     protected $context;
 
-    public function __construct(SecurityContext $context = null)
+    public function __construct(SecurityContextInterface $context = null)
     {
         $this->context = $context;
     }
@@ -53,7 +53,7 @@ class SecurityDataCollector extends DataCollector
             $this->data = array(
                 'enabled'       => true,
                 'authenticated' => $token->isAuthenticated(),
-                'user'          => (string) $token->getUser(),
+                'user'          => (string) $token,
                 'roles'         => array_map(function ($role){ return $role->getRole();}, $token->getRoles()),
             );
         }

+ 8 - 3
src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php

@@ -11,8 +11,9 @@
 
 namespace Symfony\Bundle\SecurityBundle\Templating\Helper;
 
+use Symfony\Component\Security\Acl\Voter\FieldVote;
 use Symfony\Component\Templating\Helper\Helper;
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 
 /**
  * SecurityHelper provides read-only access to the security context.
@@ -28,7 +29,7 @@ class SecurityHelper extends Helper
      *
      * @param SecurityContext $context A SecurityContext instance
      */
-    public function __construct(SecurityContext $context = null)
+    public function __construct(SecurityContextInterface $context = null)
     {
         $this->context = $context;
     }
@@ -39,7 +40,11 @@ class SecurityHelper extends Helper
             return false;
         }
 
-        return $this->context->vote($role, $object, $field);
+        if (null !== $field) {
+            $object = new FieldVote($object, $field);
+        }
+
+        return $this->context->vote($role, $object);
     }
 
     /**

+ 8 - 3
src/Symfony/Bundle/SecurityBundle/Twig/Extension/SecurityExtension.php

@@ -11,7 +11,8 @@
 
 namespace Symfony\Bundle\SecurityBundle\Twig\Extension;
 
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Acl\Voter\FieldVote;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 
 /**
  * SecurityExtension exposes security context features.
@@ -22,7 +23,7 @@ class SecurityExtension extends \Twig_Extension
 {
     protected $context;
 
-    public function __construct(SecurityContext $context = null)
+    public function __construct(SecurityContextInterface $context = null)
     {
         $this->context = $context;
     }
@@ -33,7 +34,11 @@ class SecurityExtension extends \Twig_Extension
             return false;
         }
 
-        return $this->context->vote($role, $object, $field);
+        if (null !== $field) {
+            $object = new FieldVote($object, $field);
+        }
+
+        return $this->context->vote($role, $object);
     }
 
     /**

+ 13 - 3
src/Symfony/Bundle/TwigBundle/GlobalVariables.php

@@ -36,10 +36,20 @@ class GlobalVariables
 
     public function getUser()
     {
-        $security = $this->getSecurity();
-        if ($security && $user = $security->getUser()) {
-            return $user;
+        if (!$security = $this->getSecurity()) {
+            return;
         }
+
+        if (!$token = $security->getToken()) {
+            return;
+        }
+
+        $user = $token->getUser();
+        if (!is_object($user)) {
+            return;
+        }
+
+        return $user;
     }
 
     public function getRequest()

+ 1 - 3
src/Symfony/Component/Security/Core/Authentication/Token/Token.php

@@ -85,9 +85,7 @@ abstract class Token implements TokenInterface
      */
     public function __toString()
     {
-        if (is_string($this->user)) {
-            return $this->user;
-        } else if ($this->user instanceof AccountInterface) {
+        if ($this->user instanceof AccountInterface) {
             return $this->user->getUsername();
         }
 

+ 8 - 22
src/Symfony/Component/Security/Core/SecurityContext.php

@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\Security\Core;
 
+use Symfony\Component\Security\Core\User\AccountInterface;
+use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
 use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
 use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
 use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
@@ -22,13 +24,10 @@ use Symfony\Component\Security\Acl\Voter\FieldVote;
  * It gives access to the token representing the current user authentication.
  *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class SecurityContext
+class SecurityContext implements SecurityContextInterface
 {
-    const ACCESS_DENIED_ERROR  = '_security.403_error';
-    const AUTHENTICATION_ERROR = '_security.last_error';
-    const LAST_USERNAME        = '_security.last_username';
-
     protected $token;
     protected $accessDecisionManager;
     protected $authenticationManager;
@@ -39,30 +38,17 @@ class SecurityContext
      *
      * @param AccessDecisionManagerInterface|null $accessDecisionManager An AccessDecisionManager instance
      */
-    public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager = null, $alwaysAuthenticate = false)
+    public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false)
     {
         $this->authenticationManager = $authenticationManager;
         $this->accessDecisionManager = $accessDecisionManager;
         $this->alwaysAuthenticate = $alwaysAuthenticate;
     }
 
-    public function getUser()
-    {
-        return null === $this->token ? null : $this->token->getUser();
-    }
-
-    public function vote($attributes, $object = null, $field = null)
+    public final function vote($attributes, $object = null)
     {
-        if (null === $this->token || null === $this->accessDecisionManager) {
-            return false;
-        }
-
-        if ($field !== null) {
-            if (null === $object) {
-                throw new \InvalidArgumentException('$object cannot be null when field is not null.');
-            }
-
-            $object = new FieldVote($object, $field);
+        if (null === $this->token) {
+            throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token.');
         }
 
         if ($this->alwaysAuthenticate || !$this->token->isAuthenticated()) {

+ 21 - 0
src/Symfony/Component/Security/Core/SecurityContextInterface.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace Symfony\Component\Security\Core;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * The SecurityContextInterface.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+interface SecurityContextInterface
+{
+    const ACCESS_DENIED_ERROR  = '_security.403_error';
+    const AUTHENTICATION_ERROR = '_security.last_error';
+    const LAST_USERNAME        = '_security.last_username';
+
+    function getToken();
+    function setToken(TokenInterface $account);
+    function vote($attributes, $object = null);
+}

+ 0 - 1
src/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php

@@ -16,7 +16,6 @@ use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Security\Core\Exception\AuthenticationException;
 use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
-use Symfony\Component\Security\Core\SecurityContext;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**

+ 3 - 3
src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php

@@ -17,7 +17,7 @@ use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterfa
 use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
 use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
 use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -61,12 +61,12 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
     /**
      * Constructor.
      *
-     * @param SecurityContext                $securityContext       A SecurityContext instance
+     * @param SecurityContextInterface       $securityContext       A SecurityContext instance
      * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
      * @param array                          $options               An array of options for the processing of a successful, or failed authentication attempt
      * @param LoggerInterface                $logger                A LoggerInterface instance
      */
-    public function __construct(SecurityContext $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null)
     {
         if (empty($providerKey)) {
             throw new \InvalidArgumentException('$providerKey must not be empty.');

+ 2 - 2
src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php

@@ -12,7 +12,7 @@
 namespace Symfony\Component\Security\Http\Firewall;
 
 use Symfony\Component\EventDispatcher\Event;
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -36,7 +36,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
     protected $logger;
     protected $eventDispatcher;
 
-    public function __construct(SecurityContext $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null)
     {
         $this->securityContext = $securityContext;
         $this->authenticationManager = $authenticationManager;

+ 3 - 3
src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php

@@ -11,7 +11,7 @@
 
 namespace Symfony\Component\Security\Http\Firewall;
 
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\EventDispatcher\EventInterface;
@@ -29,7 +29,7 @@ class AnonymousAuthenticationListener implements ListenerInterface
     protected $key;
     protected $logger;
 
-    public function __construct(SecurityContext $context, $key, LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null)
     {
         $this->context = $context;
         $this->key     = $key;
@@ -47,7 +47,7 @@ class AnonymousAuthenticationListener implements ListenerInterface
     {
         $dispatcher->connect('core.security', array($this, 'handle'), 0);
     }
-    
+
     /**
      * {@inheritDoc}
      */

+ 2 - 2
src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php

@@ -11,7 +11,7 @@
 
 namespace Symfony\Component\Security\Http\Firewall;
 
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
 use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
@@ -34,7 +34,7 @@ class BasicAuthenticationListener implements ListenerInterface
     protected $logger;
     protected $ignoreFailure;
 
-    public function __construct(SecurityContext $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
     {
         if (empty($providerKey)) {
             throw new \InvalidArgumentException('$providerKey must not be empty.');

+ 2 - 2
src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php

@@ -11,7 +11,7 @@
 
 namespace Symfony\Component\Security\Http\Firewall;
 
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\User\UserProviderInterface;
 use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
@@ -38,7 +38,7 @@ class DigestAuthenticationListener implements ListenerInterface
     protected $authenticationEntryPoint;
     protected $logger;
 
-    public function __construct(SecurityContext $securityContext, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null)
     {
         if (empty($providerKey)) {
             throw new \InvalidArgumentException('$providerKey must not be empty.');

+ 2 - 2
src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php

@@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
 
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
 use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
@@ -41,7 +41,7 @@ class ExceptionListener implements ListenerInterface
     protected $errorPage;
     protected $logger;
 
-    public function __construct(SecurityContext $context, AuthenticationTrustResolverInterface $trustResolver, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $context, AuthenticationTrustResolverInterface $trustResolver, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null)
     {
         $this->context = $context;
         $this->accessDeniedHandler = $accessDeniedHandler;

+ 3 - 3
src/Symfony/Component/Security/Http/Firewall/LogoutListener.php

@@ -12,7 +12,7 @@
 namespace Symfony\Component\Security\Http\Firewall;
 
 use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\EventDispatcher\EventInterface;
 use Symfony\Component\HttpFoundation\Response;
@@ -32,11 +32,11 @@ class LogoutListener implements ListenerInterface
     /**
      * Constructor
      *
-     * @param SecurityContext $securityContext
+     * @param SecurityContextInterface $securityContext
      * @param string $logoutPath The path that starts the logout process
      * @param string $targetUrl  The URL to redirect to after logout
      */
-    public function __construct(SecurityContext $securityContext, $logoutPath, $targetUrl = '/')
+    public function __construct(SecurityContextInterface $securityContext, $logoutPath, $targetUrl = '/')
     {
         $this->securityContext = $securityContext;
         $this->logoutPath = $logoutPath;

+ 2 - 2
src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php

@@ -12,7 +12,7 @@
 namespace Symfony\Component\Security\Http\Firewall;
 
 use Symfony\Component\EventDispatcher\Event;
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\User\UserProviderInterface;
 use Symfony\Component\Security\Core\User\AccountCheckerInterface;
 use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
@@ -48,7 +48,7 @@ class SwitchUserListener implements ListenerInterface
     /**
      * Constructor.
      */
-    public function __construct(SecurityContext $securityContext, UserProviderInterface $provider, AccountCheckerInterface $accountChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH')
+    public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, AccountCheckerInterface $accountChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH')
     {
         if (empty($providerKey)) {
             throw new \InvalidArgumentException('$providerKey must not be empty.');

+ 2 - 2
src/Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php

@@ -11,7 +11,7 @@
 
 namespace Symfony\Component\Security\Http\Firewall;
 
-use Symfony\Component\Security\Core\SecurityContext;
+use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -27,7 +27,7 @@ class X509AuthenticationListener extends AbstractPreAuthenticatedListener
     protected $userKey;
     protected $credentialKey;
 
-    public function __construct(SecurityContext $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null)
+    public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null)
     {
         parent::__construct($securityContext, $authenticationManager, $providerKey, $logger);
 

+ 17 - 18
tests/Symfony/Tests/Component/Security/Core/SecurityContextTest.php

@@ -16,18 +16,6 @@ use Symfony\Component\Security\Core\SecurityContext;
 
 class SecurityContextTest extends \PHPUnit_Framework_TestCase
 {
-    public function testGetUser()
-    {
-        $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'));
-
-        $this->assertNull($context->getUser());
-
-        $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
-        $token->expects($this->once())->method('getUser')->will($this->returnValue('foo'));
-        $context->setToken($token);
-        $this->assertEquals('foo', $context->getUser());
-    }
-
     public function testVoteAuthenticatesTokenIfNecessary()
     {
         $authManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
@@ -53,13 +41,21 @@ class SecurityContextTest extends \PHPUnit_Framework_TestCase
         $this->assertSame($newToken, $context->getToken());
     }
 
-    public function testVote()
+    /**
+     * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
+     */
+    public function testVoteWithoutAuthenticationToken()
     {
-        $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'));
-        $this->assertFalse($context->vote('ROLE_FOO'));
-        $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
-        $this->assertFalse($context->vote('ROLE_FOO'));
+        $context = new SecurityContext(
+            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
+            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')
+        );
+
+        $context->vote('ROLE_FOO');
+    }
 
+    public function testVote()
+    {
         $manager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
         $manager->expects($this->once())->method('decide')->will($this->returnValue(false));
         $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $manager);
@@ -85,7 +81,10 @@ class SecurityContextTest extends \PHPUnit_Framework_TestCase
 
     public function testGetSetToken()
     {
-        $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'));
+        $context = new SecurityContext(
+            $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
+            $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')
+        );
         $this->assertNull($context->getToken());
 
         $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));