summaryrefslogtreecommitdiffstats
path: root/Http
diff options
context:
space:
mode:
Diffstat (limited to 'Http')
-rw-r--r--Http/Authentication/AuthenticationUtils.php86
-rw-r--r--Http/Authentication/CustomAuthenticationFailureHandler.php45
-rw-r--r--Http/Authentication/CustomAuthenticationSuccessHandler.php49
-rw-r--r--Http/Authentication/DefaultAuthenticationFailureHandler.php40
-rw-r--r--Http/Authentication/DefaultAuthenticationSuccessHandler.php38
-rw-r--r--Http/Firewall/AbstractAuthenticationListener.php5
-rw-r--r--Http/Firewall/AnonymousAuthenticationListener.php23
-rw-r--r--Http/Firewall/ContextListener.php2
-rw-r--r--Http/Firewall/ExceptionListener.php3
-rw-r--r--Http/Firewall/RememberMeListener.php9
-rw-r--r--Http/Firewall/RemoteUserAuthenticationListener.php49
-rw-r--r--Http/Firewall/SimpleFormAuthenticationListener.php3
-rw-r--r--Http/Firewall/UsernamePasswordFormAuthenticationListener.php3
-rw-r--r--Http/HttpUtils.php15
-rw-r--r--Http/README.md2
-rw-r--r--Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php8
-rw-r--r--Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php34
-rw-r--r--Http/Tests/Firewall/ContextListenerTest.php5
-rw-r--r--Http/Tests/Firewall/RememberMeListenerTest.php111
-rw-r--r--Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php91
-rw-r--r--Http/Tests/HttpUtilsTest.php8
-rw-r--r--Http/composer.json2
22 files changed, 567 insertions, 64 deletions
diff --git a/Http/Authentication/AuthenticationUtils.php b/Http/Authentication/AuthenticationUtils.php
new file mode 100644
index 0000000..38763dc
--- /dev/null
+++ b/Http/Authentication/AuthenticationUtils.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Http\Authentication;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
+use Symfony\Component\Security\Core\Security;
+
+/**
+ * Extracts Security Errors from Request
+ *
+ * @author Boris Vujicic <boris.vujicic@gmail.com>
+ */
+class AuthenticationUtils
+{
+ /**
+ * @var RequestStack
+ */
+ private $requestStack;
+
+ /**
+ * @param RequestStack $requestStack
+ */
+ public function __construct(RequestStack $requestStack)
+ {
+ $this->requestStack = $requestStack;
+ }
+
+ /**
+ * @param bool $clearSession
+ * @return null|AuthenticationException
+ */
+ public function getLastAuthenticationError($clearSession = true)
+ {
+ $request = $this->getRequest();
+ $session = $request->getSession();
+ $authenticationException = null;
+
+ if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
+ $authenticationException = $request->attributes->get(Security::AUTHENTICATION_ERROR);
+ } elseif ($session !== null && $session->has(Security::AUTHENTICATION_ERROR)) {
+ $authenticationException = $session->get(Security::AUTHENTICATION_ERROR);
+
+ if ($clearSession) {
+ $session->remove(Security::AUTHENTICATION_ERROR);
+ }
+ }
+
+ return $authenticationException;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLastUsername()
+ {
+ $session = $this->getRequest()->getSession();
+
+ return null === $session ? '' : $session->get(Security::LAST_USERNAME);
+ }
+
+ /**
+ * @return Request
+ * @throws \LogicException
+ */
+ private function getRequest()
+ {
+ $request = $this->requestStack->getCurrentRequest();
+
+ if (null === $request) {
+ throw new \LogicException('Request should exist so it can be processed for error.');
+ }
+
+ return $request;
+ }
+}
diff --git a/Http/Authentication/CustomAuthenticationFailureHandler.php b/Http/Authentication/CustomAuthenticationFailureHandler.php
new file mode 100644
index 0000000..35bfc05
--- /dev/null
+++ b/Http/Authentication/CustomAuthenticationFailureHandler.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Http\Authentication;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CustomAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
+{
+ private $handler;
+
+ /**
+ * Constructor.
+ *
+ * @param AuthenticationFailureHandlerInterface $handler An AuthenticationFailureHandlerInterface instance
+ * @param array $options Options for processing a successful authentication attempt
+ */
+ public function __construct(AuthenticationFailureHandlerInterface $handler, array $options)
+ {
+ $this->handler = $handler;
+ if (method_exists($handler, 'setOptions')) {
+ $this->handler->setOptions($options);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
+ {
+ return $this->handler->onAuthenticationFailure($request, $exception);
+ }
+}
diff --git a/Http/Authentication/CustomAuthenticationSuccessHandler.php b/Http/Authentication/CustomAuthenticationSuccessHandler.php
new file mode 100644
index 0000000..abbb81b
--- /dev/null
+++ b/Http/Authentication/CustomAuthenticationSuccessHandler.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Http\Authentication;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
+{
+ private $handler;
+
+ /**
+ * Constructor.
+ *
+ * @param AuthenticationSuccessHandlerInterface $handler An AuthenticationFailureHandlerInterface instance
+ * @param array $options Options for processing a successful authentication attempt
+ * @param string $providerKey The provider key
+ */
+ public function __construct(AuthenticationSuccessHandlerInterface $handler, array $options, $providerKey)
+ {
+ $this->handler = $handler;
+ if (method_exists($handler, 'setOptions')) {
+ $this->handler->setOptions($options);
+ }
+ if (method_exists($handler, 'setProviderKey')) {
+ $this->handler->setProviderKey($providerKey);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onAuthenticationSuccess(Request $request, TokenInterface $token)
+ {
+ return $this->handler->onAuthenticationSuccess($request, $token);
+ }
+}
diff --git a/Http/Authentication/DefaultAuthenticationFailureHandler.php b/Http/Authentication/DefaultAuthenticationFailureHandler.php
index b3c5c4d..93150c8 100644
--- a/Http/Authentication/DefaultAuthenticationFailureHandler.php
+++ b/Http/Authentication/DefaultAuthenticationFailureHandler.php
@@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
-use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\HttpUtils;
/**
@@ -34,6 +34,12 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
protected $httpUtils;
protected $logger;
protected $options;
+ protected $defaultOptions = array(
+ 'failure_path' => null,
+ 'failure_forward' => false,
+ 'login_path' => '/login',
+ 'failure_path_parameter' => '_failure_path',
+ );
/**
* Constructor.
@@ -43,18 +49,32 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
* @param array $options Options for processing a failed authentication attempt.
* @param LoggerInterface $logger Optional logger
*/
- public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null)
+ public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options = array(), LoggerInterface $logger = null)
{
$this->httpKernel = $httpKernel;
$this->httpUtils = $httpUtils;
$this->logger = $logger;
+ $this->setOptions($options);
+ }
- $this->options = array_merge(array(
- 'failure_path' => null,
- 'failure_forward' => false,
- 'login_path' => '/login',
- 'failure_path_parameter' => '_failure_path',
- ), $options);
+ /**
+ * Gets the options.
+ *
+ * @return array An array of options
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Sets the options.
+ *
+ * @param array $options An array of options
+ */
+ public function setOptions(array $options)
+ {
+ $this->options = array_merge($this->defaultOptions, $options);
}
/**
@@ -76,7 +96,7 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
}
$subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']);
- $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);
+ $subRequest->attributes->set(Security::AUTHENTICATION_ERROR, $exception);
return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
@@ -85,7 +105,7 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
$this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path']));
}
- $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);
+ $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']);
}
diff --git a/Http/Authentication/DefaultAuthenticationSuccessHandler.php b/Http/Authentication/DefaultAuthenticationSuccessHandler.php
index 591a28d..0ee11b4 100644
--- a/Http/Authentication/DefaultAuthenticationSuccessHandler.php
+++ b/Http/Authentication/DefaultAuthenticationSuccessHandler.php
@@ -27,6 +27,13 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle
protected $httpUtils;
protected $options;
protected $providerKey;
+ protected $defaultOptions = array(
+ 'always_use_default_target_path' => false,
+ 'default_target_path' => '/',
+ 'login_path' => '/login',
+ 'target_path_parameter' => '_target_path',
+ 'use_referer' => false,
+ );
/**
* Constructor.
@@ -34,17 +41,10 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle
* @param HttpUtils $httpUtils
* @param array $options Options for processing a successful authentication attempt.
*/
- public function __construct(HttpUtils $httpUtils, array $options)
+ public function __construct(HttpUtils $httpUtils, array $options = array())
{
$this->httpUtils = $httpUtils;
-
- $this->options = array_merge(array(
- 'always_use_default_target_path' => false,
- 'default_target_path' => '/',
- 'login_path' => '/login',
- 'target_path_parameter' => '_target_path',
- 'use_referer' => false,
- ), $options);
+ $this->setOptions($options);
}
/**
@@ -56,6 +56,26 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle
}
/**
+ * Gets the options.
+ *
+ * @return array An array of options
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Sets the options.
+ *
+ * @param array $options An array of options
+ */
+ public function setOptions(array $options)
+ {
+ $this->options = array_merge($this->defaultOptions, $options);
+ }
+
+ /**
* Get the provider key.
*
* @return string
diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php
index a67d61c..d89785e 100644
--- a/Http/Firewall/AbstractAuthenticationListener.php
+++ b/Http/Firewall/AbstractAuthenticationListener.php
@@ -15,6 +15,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\Security;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
@@ -218,8 +219,8 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$this->securityContext->setToken($token);
$session = $request->getSession();
- $session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
- $session->remove(SecurityContextInterface::LAST_USERNAME);
+ $session->remove(Security::AUTHENTICATION_ERROR);
+ $session->remove(Security::LAST_USERNAME);
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
diff --git a/Http/Firewall/AnonymousAuthenticationListener.php b/Http/Firewall/AnonymousAuthenticationListener.php
index 446dfec..68f8987 100644
--- a/Http/Firewall/AnonymousAuthenticationListener.php
+++ b/Http/Firewall/AnonymousAuthenticationListener.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Http\Firewall;
+use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -26,12 +28,14 @@ class AnonymousAuthenticationListener implements ListenerInterface
{
private $context;
private $key;
+ private $authenticationManager;
private $logger;
- public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null)
+ public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null, AuthenticationManagerInterface $authenticationManager = null)
{
$this->context = $context;
$this->key = $key;
+ $this->authenticationManager = $authenticationManager;
$this->logger = $logger;
}
@@ -46,10 +50,21 @@ class AnonymousAuthenticationListener implements ListenerInterface
return;
}
- $this->context->setToken(new AnonymousToken($this->key, 'anon.', array()));
+ try {
+ $token = new AnonymousToken($this->key, 'anon.', array());
+ if (null !== $this->authenticationManager) {
+ $token = $this->authenticationManager->authenticate($token);
+ }
- if (null !== $this->logger) {
- $this->logger->info('Populated SecurityContext with an anonymous Token');
+ $this->context->setToken($token);
+
+ if (null !== $this->logger) {
+ $this->logger->info('Populated SecurityContext with an anonymous Token');
+ }
+ } catch (AuthenticationException $failed) {
+ if (null !== $this->logger) {
+ $this->logger->info(sprintf('Anonymous authentication failed: %s', $failed->getMessage()));
+ }
}
}
}
diff --git a/Http/Firewall/ContextListener.php b/Http/Firewall/ContextListener.php
index 435c440..e61907e 100644
--- a/Http/Firewall/ContextListener.php
+++ b/Http/Firewall/ContextListener.php
@@ -142,7 +142,7 @@ class ContextListener implements ListenerInterface
*
* @throws \RuntimeException
*/
- private function refreshUser(TokenInterface $token)
+ protected function refreshUser(TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof UserInterface) {
diff --git a/Http/Firewall/ExceptionListener.php b/Http/Firewall/ExceptionListener.php
index d0b167e..e224ea3 100644
--- a/Http/Firewall/ExceptionListener.php
+++ b/Http/Firewall/ExceptionListener.php
@@ -13,6 +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\Security;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
@@ -146,7 +147,7 @@ class ExceptionListener
}
} elseif (null !== $this->errorPage) {
$subRequest = $this->httpUtils->createRequest($event->getRequest(), $this->errorPage);
- $subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception);
+ $subRequest->attributes->set(Security::ACCESS_DENIED_ERROR, $exception);
$event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true));
}
diff --git a/Http/Firewall/RememberMeListener.php b/Http/Firewall/RememberMeListener.php
index 6ca3842..44000d3 100644
--- a/Http/Firewall/RememberMeListener.php
+++ b/Http/Firewall/RememberMeListener.php
@@ -33,6 +33,7 @@ class RememberMeListener implements ListenerInterface
private $authenticationManager;
private $logger;
private $dispatcher;
+ private $catchExceptions = true;
/**
* Constructor.
@@ -42,14 +43,16 @@ class RememberMeListener implements ListenerInterface
* @param AuthenticationManagerInterface $authenticationManager
* @param LoggerInterface $logger
* @param EventDispatcherInterface $dispatcher
+ * @param bool $catchExceptions
*/
- public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
+ public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $catchExceptions = true)
{
$this->securityContext = $securityContext;
$this->rememberMeServices = $rememberMeServices;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
+ $this->catchExceptions = $catchExceptions;
}
/**
@@ -90,6 +93,10 @@ class RememberMeListener implements ListenerInterface
}
$this->rememberMeServices->loginFail($request);
+
+ if (!$this->catchExceptions) {
+ throw $failed;
+ }
}
}
}
diff --git a/Http/Firewall/RemoteUserAuthenticationListener.php b/Http/Firewall/RemoteUserAuthenticationListener.php
new file mode 100644
index 0000000..f190a17
--- /dev/null
+++ b/Http/Firewall/RemoteUserAuthenticationListener.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Http\Firewall;
+
+use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * REMOTE_USER authentication listener.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Maxime Douailin <maxime.douailin@gmail.com>
+ */
+class RemoteUserAuthenticationListener extends AbstractPreAuthenticatedListener
+{
+ private $userKey;
+
+ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'REMOTE_USER', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
+ {
+ parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $dispatcher);
+
+ $this->userKey = $userKey;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getPreAuthenticatedData(Request $request)
+ {
+ if (!$request->server->has($this->userKey)) {
+ throw new BadCredentialsException(sprintf('User key was not found: %s', $this->userKey));
+ }
+
+ return array($request->server->get($this->userKey), null);
+ }
+}
diff --git a/Http/Firewall/SimpleFormAuthenticationListener.php b/Http/Firewall/SimpleFormAuthenticationListener.php
index 5b905df..7f27b7f 100644
--- a/Http/Firewall/SimpleFormAuthenticationListener.php
+++ b/Http/Firewall/SimpleFormAuthenticationListener.php
@@ -23,6 +23,7 @@ use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerI
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface;
+use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
@@ -114,7 +115,7 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener
$password = $request->get($this->options['password_parameter'], null, true);
}
- $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);
+ $request->getSession()->set(Security::LAST_USERNAME, $username);
$token = $this->simpleAuthenticator->createToken($request, $username, $password, $this->providerKey);
diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
index 36ff758..b857fb3 100644
--- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
+++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
@@ -25,6 +25,7 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterfac
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
+use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -93,7 +94,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
$password = $request->get($this->options['password_parameter'], null, true);
}
- $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);
+ $request->getSession()->set(Security::LAST_USERNAME, $username);
return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
}
diff --git a/Http/HttpUtils.php b/Http/HttpUtils.php
index 451c12c..fbcfdb7 100644
--- a/Http/HttpUtils.php
+++ b/Http/HttpUtils.php
@@ -11,8 +11,6 @@
namespace Symfony\Component\Security\Http;
-use Symfony\Component\Security\Core\SecurityContextInterface;
-
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
@@ -20,6 +18,7 @@ use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Security\Core\Security;
/**
* Encapsulates the logic needed to create sub-requests, redirect the user, and match URLs.
@@ -77,14 +76,14 @@ class HttpUtils
$newRequest->setSession($request->getSession());
}
- if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
- $newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR));
+ if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
+ $newRequest->attributes->set(Security::AUTHENTICATION_ERROR, $request->attributes->get(Security::AUTHENTICATION_ERROR));
}
- if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) {
- $newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR));
+ if ($request->attributes->has(Security::ACCESS_DENIED_ERROR)) {
+ $newRequest->attributes->set(Security::ACCESS_DENIED_ERROR, $request->attributes->get(Security::ACCESS_DENIED_ERROR));
}
- if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) {
- $newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME));
+ if ($request->attributes->has(Security::LAST_USERNAME)) {
+ $newRequest->attributes->set(Security::LAST_USERNAME, $request->attributes->get(Security::LAST_USERNAME));
}
return $newRequest;
diff --git a/Http/README.md b/Http/README.md
index c0760d4..e19af42 100644
--- a/Http/README.md
+++ b/Http/README.md
@@ -11,7 +11,7 @@ Resources
Documentation:
-http://symfony.com/doc/2.5/book/security.html
+http://symfony.com/doc/2.6/book/security.html
Tests
-----
diff --git a/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php b/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php
index 15adcdf..e065660 100644
--- a/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php
+++ b/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\Security\Http\Tests\Authentication;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
-use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class DefaultAuthenticationFailureHandlerTest extends \PHPUnit_Framework_TestCase
@@ -47,7 +47,7 @@ class DefaultAuthenticationFailureHandlerTest extends \PHPUnit_Framework_TestCas
$subRequest = $this->getRequest();
$subRequest->attributes->expects($this->once())
- ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception);
+ ->method('set')->with(Security::AUTHENTICATION_ERROR, $this->exception);
$this->httpUtils->expects($this->once())
->method('createRequest')->with($this->request, '/login')
->will($this->returnValue($subRequest));
@@ -79,7 +79,7 @@ class DefaultAuthenticationFailureHandlerTest extends \PHPUnit_Framework_TestCas
public function testExceptionIsPersistedInSession()
{
$this->session->expects($this->once())
- ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception);
+ ->method('set')->with(Security::AUTHENTICATION_ERROR, $this->exception);
$handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger);
$handler->onAuthenticationFailure($this->request, $this->exception);
@@ -91,7 +91,7 @@ class DefaultAuthenticationFailureHandlerTest extends \PHPUnit_Framework_TestCas
$subRequest = $this->getRequest();
$subRequest->attributes->expects($this->once())
- ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception);
+ ->method('set')->with(Security::AUTHENTICATION_ERROR, $this->exception);
$this->httpUtils->expects($this->once())
->method('createRequest')->with($this->request, '/login')
diff --git a/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php b/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php
index 1fb7350..0f43aa0 100644
--- a/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php
+++ b/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Security\Http\Tests\Firewall;
+use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Http\Firewall\AnonymousAuthenticationListener;
class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
@@ -28,7 +29,13 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
->method('setToken')
;
- $listener = new AnonymousAuthenticationListener($context, 'TheKey');
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+ $authenticationManager
+ ->expects($this->never())
+ ->method('authenticate')
+ ;
+
+ $listener = new AnonymousAuthenticationListener($context, 'TheKey', null, $authenticationManager);
$listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false));
}
@@ -40,16 +47,27 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
->method('getToken')
->will($this->returnValue(null))
;
- $context
+
+ $anonymousToken = new AnonymousToken('TheKey', 'anon.', array());
+
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+ $authenticationManager
->expects($this->once())
- ->method('setToken')
+ ->method('authenticate')
->with(self::logicalAnd(
- $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken'),
- $this->attributeEqualTo('key', 'TheKey')
+ $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken'),
+ $this->attributeEqualTo('key', 'TheKey')
))
+ ->will($this->returnValue($anonymousToken))
;
- $listener = new AnonymousAuthenticationListener($context, 'TheKey');
+ $context
+ ->expects($this->once())
+ ->method('setToken')
+ ->with($anonymousToken)
+ ;
+
+ $listener = new AnonymousAuthenticationListener($context, 'TheKey', null, $authenticationManager);
$listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false));
}
@@ -66,7 +84,9 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
->with('Populated SecurityContext with an anonymous Token')
;
- $listener = new AnonymousAuthenticationListener($context, 'TheKey', $logger);
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+
+ $listener = new AnonymousAuthenticationListener($context, 'TheKey', $logger, $authenticationManager);
$listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false));
}
}
diff --git a/Http/Tests/Firewall/ContextListenerTest.php b/Http/Tests/Firewall/ContextListenerTest.php
index d6bc5b4..90af07e 100644
--- a/Http/Tests/Firewall/ContextListenerTest.php
+++ b/Http/Tests/Firewall/ContextListenerTest.php
@@ -18,6 +18,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Http\Firewall\ContextListener;
@@ -27,8 +28,8 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->securityContext = new SecurityContext(
- $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'),
- $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')
+ new TokenStorage(),
+ $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')
);
}
diff --git a/Http/Tests/Firewall/RememberMeListenerTest.php b/Http/Tests/Firewall/RememberMeListenerTest.php
index 9506692..68dfc14 100644
--- a/Http/Tests/Firewall/RememberMeListenerTest.php
+++ b/Http/Tests/Firewall/RememberMeListenerTest.php
@@ -14,12 +14,13 @@ namespace Symfony\Component\Security\Http\Tests\Firewall;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Firewall\RememberMeListener;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Http\SecurityEvents;
class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
{
public function testOnCoreSecurityDoesNotTryToPopulateNonEmptySecurityContext()
{
- list($listener, $context, $service,,) = $this->getListener();
+ list($listener, $context,,,,) = $this->getListener();
$context
->expects($this->once())
@@ -99,6 +100,48 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$listener->handle($event);
}
+ /**
+ * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException
+ * @expectedExceptionMessage Authentication failed.
+ */
+ public function testOnCoreSecurityIgnoresAuthenticationOptionallyRethrowsExceptionThrownAuthenticationManagerImplementation()
+ {
+ list($listener, $context, $service, $manager,) = $this->getListener(false, false);
+
+ $context
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue(null))
+ ;
+
+ $service
+ ->expects($this->once())
+ ->method('autoLogin')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')))
+ ;
+
+ $service
+ ->expects($this->once())
+ ->method('loginFail')
+ ;
+
+ $exception = new AuthenticationException('Authentication failed.');
+ $manager
+ ->expects($this->once())
+ ->method('authenticate')
+ ->will($this->throwException($exception))
+ ;
+
+ $event = $this->getGetResponseEvent();
+ $event
+ ->expects($this->once())
+ ->method('getRequest')
+ ->will($this->returnValue(new Request()))
+ ;
+
+ $listener->handle($event);
+ }
+
public function testOnCoreSecurity()
{
list($listener, $context, $service, $manager,) = $this->getListener();
@@ -138,6 +181,55 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$listener->handle($event);
}
+ public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherIsPresent()
+ {
+ list($listener, $context, $service, $manager,, $dispatcher) = $this->getListener(true);
+
+ $context
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue(null))
+ ;
+
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $service
+ ->expects($this->once())
+ ->method('autoLogin')
+ ->will($this->returnValue($token))
+ ;
+
+ $context
+ ->expects($this->once())
+ ->method('setToken')
+ ->with($this->equalTo($token))
+ ;
+
+ $manager
+ ->expects($this->once())
+ ->method('authenticate')
+ ->will($this->returnValue($token))
+ ;
+
+ $event = $this->getGetResponseEvent();
+ $request = new Request();
+ $event
+ ->expects($this->once())
+ ->method('getRequest')
+ ->will($this->returnValue($request))
+ ;
+
+ $dispatcher
+ ->expects($this->once())
+ ->method('dispatch')
+ ->with(
+ SecurityEvents::INTERACTIVE_LOGIN,
+ $this->isInstanceOf('Symfony\Component\Security\Http\Event\InteractiveLoginEvent')
+ )
+ ;
+
+ $listener->handle($event);
+ }
+
protected function getGetResponseEvent()
{
return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
@@ -148,16 +240,18 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false);
}
- protected function getListener()
+ protected function getListener($withDispatcher = false, $catchExceptions = true)
{
$listener = new RememberMeListener(
$context = $this->getContext(),
$service = $this->getService(),
$manager = $this->getManager(),
- $logger = $this->getLogger()
+ $logger = $this->getLogger(),
+ $dispatcher = ($withDispatcher ? $this->getDispatcher() : null),
+ $catchExceptions
);
- return array($listener, $context, $service, $manager, $logger);
+ return array($listener, $context, $service, $manager, $logger, $dispatcher);
}
protected function getLogger()
@@ -177,8 +271,11 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
protected function getContext()
{
- return $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext')
- ->disableOriginalConstructor()
- ->getMock();
+ return $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+ }
+
+ protected function getDispatcher()
+ {
+ return $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
}
}
diff --git a/Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php b/Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php
new file mode 100644
index 0000000..2bc1ad6
--- /dev/null
+++ b/Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php
@@ -0,0 +1,91 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Http\Tests\Firewall;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Http\Firewall\RemoteUserAuthenticationListener;
+
+class RemoteUserAuthenticationListenerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetPreAuthenticatedData()
+ {
+ $serverVars = array(
+ 'REMOTE_USER' => 'TheUser'
+ );
+
+ $request = new Request(array(), array(), array(), array(), array(), $serverVars);
+
+ $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+
+ $listener = new RemoteUserAuthenticationListener(
+ $context,
+ $authenticationManager,
+ 'TheProviderKey'
+ );
+
+ $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
+ $method->setAccessible(true);
+
+ $result = $method->invokeArgs($listener, array($request));
+ $this->assertSame($result, array('TheUser', null));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testGetPreAuthenticatedDataNoUser()
+ {
+ $request = new Request(array(), array(), array(), array(), array(), array());
+
+ $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+
+ $listener = new RemoteUserAuthenticationListener(
+ $context,
+ $authenticationManager,
+ 'TheProviderKey'
+ );
+
+ $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
+ $method->setAccessible(true);
+
+ $result = $method->invokeArgs($listener, array($request));
+ }
+
+ public function testGetPreAuthenticatedDataWithDifferentKeys()
+ {
+ $userCredentials = array('TheUser', null);
+
+ $request = new Request(array(), array(), array(), array(), array(), array(
+ 'TheUserKey' => 'TheUser'
+ ));
+ $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+
+ $listener = new RemoteUserAuthenticationListener(
+ $context,
+ $authenticationManager,
+ 'TheProviderKey',
+ 'TheUserKey'
+ );
+
+ $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
+ $method->setAccessible(true);
+
+ $result = $method->invokeArgs($listener, array($request));
+ $this->assertSame($result, $userCredentials);
+ }
+}
diff --git a/Http/Tests/HttpUtilsTest.php b/Http/Tests/HttpUtilsTest.php
index 5cac504..195fc48 100644
--- a/Http/Tests/HttpUtilsTest.php
+++ b/Http/Tests/HttpUtilsTest.php
@@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Http\Tests;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
-use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\HttpUtils;
class HttpUtilsTest extends \PHPUnit_Framework_TestCase
@@ -126,9 +126,9 @@ class HttpUtilsTest extends \PHPUnit_Framework_TestCase
public function provideSecurityContextAttributes()
{
return array(
- array(SecurityContextInterface::AUTHENTICATION_ERROR),
- array(SecurityContextInterface::ACCESS_DENIED_ERROR),
- array(SecurityContextInterface::LAST_USERNAME),
+ array(Security::AUTHENTICATION_ERROR),
+ array(Security::ACCESS_DENIED_ERROR),
+ array(Security::LAST_USERNAME),
);
}
diff --git a/Http/composer.json b/Http/composer.json
index c544ad1..8129523 100644
--- a/Http/composer.json
+++ b/Http/composer.json
@@ -38,7 +38,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.5-dev"
+ "dev-master": "2.6-dev"
}
}
}