summaryrefslogtreecommitdiffstats
path: root/Http
diff options
context:
space:
mode:
Diffstat (limited to 'Http')
-rw-r--r--Http/Authentication/DefaultAuthenticationFailureHandler.php13
-rw-r--r--Http/EntryPoint/BasicAuthenticationEntryPoint.php2
-rw-r--r--Http/EntryPoint/DigestAuthenticationEntryPoint.php4
-rw-r--r--Http/Firewall.php9
-rw-r--r--Http/Firewall/AbstractAuthenticationListener.php7
-rw-r--r--Http/Firewall/AbstractPreAuthenticatedListener.php2
-rw-r--r--Http/Firewall/AccessListener.php5
-rw-r--r--Http/Firewall/AnonymousAuthenticationListener.php2
-rw-r--r--Http/Firewall/BasicAuthenticationListener.php2
-rw-r--r--Http/Firewall/ChannelListener.php2
-rw-r--r--Http/Firewall/ContextListener.php8
-rw-r--r--Http/Firewall/DigestAuthenticationListener.php4
-rw-r--r--Http/Firewall/ExceptionListener.php8
-rw-r--r--Http/Firewall/LogoutListener.php4
-rw-r--r--Http/Firewall/RememberMeListener.php4
-rw-r--r--Http/Firewall/SwitchUserListener.php9
-rw-r--r--Http/Firewall/UsernamePasswordFormAuthenticationListener.php21
-rw-r--r--Http/Firewall/X509AuthenticationListener.php2
-rw-r--r--Http/HttpUtils.php13
-rw-r--r--Http/RememberMe/AbstractRememberMeServices.php19
-rw-r--r--Http/RememberMe/PersistentTokenBasedRememberMeServices.php56
-rw-r--r--Http/RememberMe/ResponseListener.php9
-rw-r--r--Http/RememberMe/TokenBasedRememberMeServices.php2
23 files changed, 126 insertions, 81 deletions
diff --git a/Http/Authentication/DefaultAuthenticationFailureHandler.php b/Http/Authentication/DefaultAuthenticationFailureHandler.php
index 61d77a8..64f84f0 100644
--- a/Http/Authentication/DefaultAuthenticationFailureHandler.php
+++ b/Http/Authentication/DefaultAuthenticationFailureHandler.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Authentication;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\HttpUtils;
@@ -50,9 +50,10 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
$this->logger = $logger;
$this->options = array_merge(array(
- 'failure_path' => null,
- 'failure_forward' => false,
- 'login_path' => '/login',
+ 'failure_path' => null,
+ 'failure_forward' => false,
+ 'login_path' => '/login',
+ 'failure_path_parameter' => '_failure_path'
), $options);
}
@@ -61,6 +62,10 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
+ if ($failureUrl = $request->get($this->options['failure_path_parameter'], null, true)) {
+ $this->options['failure_path'] = $failureUrl;
+ }
+
if (null === $this->options['failure_path']) {
$this->options['failure_path'] = $this->options['login_path'];
}
diff --git a/Http/EntryPoint/BasicAuthenticationEntryPoint.php b/Http/EntryPoint/BasicAuthenticationEntryPoint.php
index 6ba3872..44ece5e 100644
--- a/Http/EntryPoint/BasicAuthenticationEntryPoint.php
+++ b/Http/EntryPoint/BasicAuthenticationEntryPoint.php
@@ -34,7 +34,7 @@ class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
$response = new Response();
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
- $response->setStatusCode(401, $authException ? $authException->getMessage() : null);
+ $response->setStatusCode(401);
return $response;
}
diff --git a/Http/EntryPoint/DigestAuthenticationEntryPoint.php b/Http/EntryPoint/DigestAuthenticationEntryPoint.php
index ec92419..1131b58 100644
--- a/Http/EntryPoint/DigestAuthenticationEntryPoint.php
+++ b/Http/EntryPoint/DigestAuthenticationEntryPoint.php
@@ -16,7 +16,7 @@ use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
/**
* DigestAuthenticationEntryPoint starts an HTTP Digest authentication.
@@ -57,7 +57,7 @@ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterfac
$response = new Response();
$response->headers->set('WWW-Authenticate', $authenticateHeader);
- $response->setStatusCode(401, $authException ? $authException->getMessage() : null);
+ $response->setStatusCode(401);
return $response;
}
diff --git a/Http/Firewall.php b/Http/Firewall.php
index a590fd9..e083fdb 100644
--- a/Http/Firewall.php
+++ b/Http/Firewall.php
@@ -12,8 +12,10 @@
namespace Symfony\Component\Security\Http;
use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Firewall uses a FirewallMap to register security listeners for the given
@@ -25,7 +27,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class Firewall
+class Firewall implements EventSubscriberInterface
{
private $map;
private $dispatcher;
@@ -68,4 +70,9 @@ class Firewall
}
}
}
+
+ public static function getSubscribedEvents()
+ {
+ return array(KernelEvents::REQUEST => array('onKernelRequest', 8));
+ }
}
diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php
index 410fb73..80f47f7 100644
--- a/Http/Firewall/AbstractAuthenticationListener.php
+++ b/Http/Firewall/AbstractAuthenticationListener.php
@@ -19,7 +19,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -75,6 +75,8 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
* successful, or failed authentication attempt
* @param LoggerInterface $logger A LoggerInterface instance
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
+ *
+ * @throws \InvalidArgumentException
*/
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
@@ -110,6 +112,9 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
* Handles form based authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
+ *
+ * @throws \RuntimeException
+ * @throws SessionUnavailableException
*/
final public function handle(GetResponseEvent $event)
{
diff --git a/Http/Firewall/AbstractPreAuthenticatedListener.php b/Http/Firewall/AbstractPreAuthenticatedListener.php
index 66041be..d7e46cf 100644
--- a/Http/Firewall/AbstractPreAuthenticatedListener.php
+++ b/Http/Firewall/AbstractPreAuthenticatedListener.php
@@ -18,7 +18,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
diff --git a/Http/Firewall/AccessListener.php b/Http/Firewall/AccessListener.php
index 3e2d3a5..c3894ef 100644
--- a/Http/Firewall/AccessListener.php
+++ b/Http/Firewall/AccessListener.php
@@ -15,7 +15,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -46,6 +46,9 @@ class AccessListener implements ListenerInterface
* Handles access authorization.
*
* @param GetResponseEvent $event A GetResponseEvent instance
+ *
+ * @throws AccessDeniedException
+ * @throws AuthenticationCredentialsNotFoundException
*/
public function handle(GetResponseEvent $event)
{
diff --git a/Http/Firewall/AnonymousAuthenticationListener.php b/Http/Firewall/AnonymousAuthenticationListener.php
index d00865d..af2213b 100644
--- a/Http/Firewall/AnonymousAuthenticationListener.php
+++ b/Http/Firewall/AnonymousAuthenticationListener.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\SecurityContextInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
diff --git a/Http/Firewall/BasicAuthenticationListener.php b/Http/Firewall/BasicAuthenticationListener.php
index e331179..5b1c8b3 100644
--- a/Http/Firewall/BasicAuthenticationListener.php
+++ b/Http/Firewall/BasicAuthenticationListener.php
@@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Http\Firewall;
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;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
diff --git a/Http/Firewall/ChannelListener.php b/Http/Firewall/ChannelListener.php
index 9b0f8c6..9e4a6ee 100644
--- a/Http/Firewall/ChannelListener.php
+++ b/Http/Firewall/ChannelListener.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
diff --git a/Http/Firewall/ContextListener.php b/Http/Firewall/ContextListener.php
index c24c879..8c71876 100644
--- a/Http/Firewall/ContextListener.php
+++ b/Http/Firewall/ContextListener.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
@@ -88,7 +88,7 @@ class ContextListener implements ListenerInterface
$token = $this->refreshUser($token);
} elseif (null !== $token) {
if (null !== $this->logger) {
- $this->logger->warn(sprintf('Session includes a "%s" where a security token is expected', is_object($token) ? get_class($token) : gettype($token)));
+ $this->logger->warning(sprintf('Session includes a "%s" where a security token is expected', is_object($token) ? get_class($token) : gettype($token)));
}
$token = null;
@@ -138,6 +138,8 @@ class ContextListener implements ListenerInterface
* @param TokenInterface $token
*
* @return TokenInterface|null
+ *
+ * @throws \RuntimeException
*/
private function refreshUser(TokenInterface $token)
{
@@ -163,7 +165,7 @@ class ContextListener implements ListenerInterface
// let's try the next user provider
} catch (UsernameNotFoundException $notFound) {
if (null !== $this->logger) {
- $this->logger->warn(sprintf('Username "%s" could not be found.', $user->getUsername()));
+ $this->logger->warning(sprintf('Username "%s" could not be found.', $user->getUsername()));
}
return null;
diff --git a/Http/Firewall/DigestAuthenticationListener.php b/Http/Firewall/DigestAuthenticationListener.php
index 2bc4aa5..7ab3dcf 100644
--- a/Http/Firewall/DigestAuthenticationListener.php
+++ b/Http/Firewall/DigestAuthenticationListener.php
@@ -14,7 +14,7 @@ namespace Symfony\Component\Security\Http\Firewall;
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;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
@@ -54,6 +54,8 @@ class DigestAuthenticationListener implements ListenerInterface
* Handles digest authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
+ *
+ * @throws AuthenticationServiceException
*/
public function handle(GetResponseEvent $event)
{
diff --git a/Http/Firewall/ExceptionListener.php b/Http/Firewall/ExceptionListener.php
index f134f9c..0f81d1b 100644
--- a/Http/Firewall/ExceptionListener.php
+++ b/Http/Firewall/ExceptionListener.php
@@ -23,7 +23,7 @@ use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationExceptio
use Symfony\Component\Security\Core\Exception\LogoutException;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
@@ -106,7 +106,9 @@ class ExceptionListener
}
try {
- $response = $this->startAuthentication($request, new InsufficientAuthenticationException('Full authentication is required to access this resource.', $token, 0, $exception));
+ $insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception);
+ $insufficientAuthenticationException->setToken($token);
+ $response = $this->startAuthentication($request, $insufficientAuthenticationException);
} catch (\Exception $e) {
$event->setException($e);
@@ -134,7 +136,7 @@ class ExceptionListener
}
} catch (\Exception $e) {
if (null !== $this->logger) {
- $this->logger->err(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()));
+ $this->logger->error(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()));
}
$event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
diff --git a/Http/Firewall/LogoutListener.php b/Http/Firewall/LogoutListener.php
index 32a0511..ca2f439 100644
--- a/Http/Firewall/LogoutListener.php
+++ b/Http/Firewall/LogoutListener.php
@@ -75,8 +75,10 @@ class LogoutListener implements ListenerInterface
* validate the request.
*
* @param GetResponseEvent $event A GetResponseEvent instance
+ *
* @throws InvalidCsrfTokenException if the CSRF token is invalid
- * @throws RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
+ * @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
+ * @throws LogoutException
*/
public function handle(GetResponseEvent $event)
{
diff --git a/Http/Firewall/RememberMeListener.php b/Http/Firewall/RememberMeListener.php
index 3614f79..5a856e2 100644
--- a/Http/Firewall/RememberMeListener.php
+++ b/Http/Firewall/RememberMeListener.php
@@ -11,7 +11,7 @@
namespace Symfony\Component\Security\Http\Firewall;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
@@ -82,7 +82,7 @@ class RememberMeListener implements ListenerInterface
}
} catch (AuthenticationException $failed) {
if (null !== $this->logger) {
- $this->logger->warn(
+ $this->logger->warning(
'SecurityContext not populated with remember-me token as the'
.' AuthenticationManager rejected the AuthenticationToken returned'
.' by the RememberMeServices: '.$failed->getMessage()
diff --git a/Http/Firewall/SwitchUserListener.php b/Http/Firewall/SwitchUserListener.php
index 7f0aa78..bad6b2b 100644
--- a/Http/Firewall/SwitchUserListener.php
+++ b/Http/Firewall/SwitchUserListener.php
@@ -16,7 +16,7 @@ use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -71,6 +71,8 @@ class SwitchUserListener implements ListenerInterface
* Handles digest authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
+ *
+ * @throws \LogicException
*/
public function handle(GetResponseEvent $event)
{
@@ -102,6 +104,9 @@ class SwitchUserListener implements ListenerInterface
* @param Request $request A Request instance
*
* @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise
+ *
+ * @throws \LogicException
+ * @throws AccessDeniedException
*/
private function attemptSwitchUser(Request $request)
{
@@ -148,6 +153,8 @@ class SwitchUserListener implements ListenerInterface
* @param Request $request A Request instance
*
* @return TokenInterface The original TokenInterface instance
+ *
+ * @throws AuthenticationCredentialsNotFoundException
*/
private function attemptExitUser(Request $request)
{
diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
index 22330a8..81c2b37 100644
--- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
+++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
@@ -55,7 +55,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
*/
protected function requiresAuthentication(Request $request)
{
- if ($this->options['post_only'] && !$request->isMethod('post')) {
+ if ($this->options['post_only'] && !$request->isMethod('POST')) {
return false;
}
@@ -67,14 +67,6 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
*/
protected function attemptAuthentication(Request $request)
{
- if ($this->options['post_only'] && 'post' !== strtolower($request->getMethod())) {
- if (null !== $this->logger) {
- $this->logger->debug(sprintf('Authentication method not supported: %s.', $request->getMethod()));
- }
-
- return null;
- }
-
if (null !== $this->csrfProvider) {
$csrfToken = $request->get($this->options['csrf_parameter'], null, true);
@@ -83,8 +75,13 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
}
}
- $username = trim($request->get($this->options['username_parameter'], null, true));
- $password = $request->get($this->options['password_parameter'], null, true);
+ if ($this->options['post_only']) {
+ $username = trim($request->request->get($this->options['username_parameter'], null, true));
+ $password = $request->request->get($this->options['password_parameter'], null, true);
+ } else {
+ $username = trim($request->get($this->options['username_parameter'], null, true));
+ $password = $request->get($this->options['password_parameter'], null, true);
+ }
$request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);
diff --git a/Http/Firewall/X509AuthenticationListener.php b/Http/Firewall/X509AuthenticationListener.php
index 2f4b78a..0b5a6ae 100644
--- a/Http/Firewall/X509AuthenticationListener.php
+++ b/Http/Firewall/X509AuthenticationListener.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
diff --git a/Http/HttpUtils.php b/Http/HttpUtils.php
index 7e6679e..0453520 100644
--- a/Http/HttpUtils.php
+++ b/Http/HttpUtils.php
@@ -35,7 +35,7 @@ class HttpUtils
* Constructor.
*
* @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface instance
- * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
+ * @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher The Url or Request matcher
*/
public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null)
{
@@ -71,8 +71,8 @@ class HttpUtils
public function createRequest(Request $request, $path)
{
$newRequest = $request::create($this->generateUri($request, $path), 'get', array(), $request->cookies->all(), array(), $request->server->all());
- if ($session = $request->getSession()) {
- $newRequest->setSession($session);
+ if ($request->hasSession()) {
+ $newRequest->setSession($request->getSession());
}
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
@@ -136,16 +136,11 @@ class HttpUtils
return $request->getUriForPath($path);
}
- return $this->generateUrl($path, $request->attributes->all(), true);
- }
-
- private function generateUrl($route, array $attributes = array(), $absolute = false)
- {
if (null === $this->urlGenerator) {
throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.');
}
- $url = $this->urlGenerator->generate($route, $attributes, $absolute);
+ $url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL);
// unnecessary query string parameters must be removed from url
// (ie. query parameters that are presents in $attributes)
diff --git a/Http/RememberMe/AbstractRememberMeServices.php b/Http/RememberMe/AbstractRememberMeServices.php
index 4f7c5b9..ae61dd7 100644
--- a/Http/RememberMe/AbstractRememberMeServices.php
+++ b/Http/RememberMe/AbstractRememberMeServices.php
@@ -22,7 +22,7 @@ use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Cookie;
-use Symfony\Component\HttpKernel\Log\LoggerInterface;
+use Psr\Log\LoggerInterface;
/**
* Base class implementing the RememberMeServicesInterface
@@ -47,6 +47,8 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
* @param string $providerKey
* @param array $options
* @param LoggerInterface $logger
+ *
+ * @throws \InvalidArgumentException
*/
public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null)
{
@@ -89,7 +91,9 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
*
* @param Request $request
*
- * @return TokenInterface
+ * @return TokenInterface|null
+ *
+ * @throws CookieTheftException
*/
final public function autoLogin(Request $request)
{
@@ -125,7 +129,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
}
} catch (UnsupportedUserException $unSupported) {
if (null !== $this->logger) {
- $this->logger->warn('User class for remember-me cookie not supported.');
+ $this->logger->warning('User class for remember-me cookie not supported.');
}
} catch (AuthenticationException $invalid) {
if (null !== $this->logger) {
@@ -172,6 +176,9 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
*/
final public function loginSuccess(Request $request, Response $response, TokenInterface $token)
{
+ // Make sure any old remember-me cookies are cancelled
+ $this->cancelCookie($request);
+
if (!$token->getUser() instanceof UserInterface) {
if (null !== $this->logger) {
$this->logger->debug('Remember-me ignores token since it does not contain a UserInterface implementation.');
@@ -192,6 +199,12 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
$this->logger->debug('Remember-me was requested; setting cookie.');
}
+ // Remove attribute from request that sets a NULL cookie.
+ // It was set by $this->cancelCookie()
+ // (cancelCookie does other things too for some RememberMeServices
+ // so we should still call it at the start of this method)
+ $request->attributes->remove(self::COOKIE_ATTR_NAME);
+
$this->onLoginSuccess($request, $response, $token);
}
diff --git a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
index 8944672..6500bfd 100644
--- a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
+++ b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
@@ -19,6 +19,8 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CookieTheftException;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Util\SecureRandomInterface;
+use Psr\Log\LoggerInterface;
/**
* Concrete implementation of the RememberMeServicesInterface which needs
@@ -30,6 +32,24 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
{
private $tokenProvider;
+ private $secureRandom;
+
+ /**
+ * Constructor.
+ *
+ * @param array $userProviders
+ * @param string $key
+ * @param string $providerKey
+ * @param array $options
+ * @param LoggerInterface $logger
+ * @param SecureRandomInterface $secureRandom
+ */
+ public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null, SecureRandomInterface $secureRandom)
+ {
+ parent::__construct($userProviders, $key, $providerKey, $options, $logger);
+
+ $this->secureRandom = $secureRandom;
+ }
/**
* Sets the token provider
@@ -44,10 +64,12 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
/**
* {@inheritDoc}
*/
- public function logout(Request $request, Response $response, TokenInterface $token)
+ protected function cancelCookie(Request $request)
{
- parent::logout($request, $response, $token);
+ // Delete cookie on the client
+ parent::cancelCookie($request);
+ // Delete cookie from the tokenProvider
if (null !== ($cookie = $request->cookies->get($this->options['name']))
&& count($parts = $this->decodeCookie($cookie)) === 2
) {
@@ -69,8 +91,6 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
$persistentToken = $this->tokenProvider->loadTokenBySeries($series);
if ($persistentToken->getTokenValue() !== $tokenValue) {
- $this->tokenProvider->deleteTokenBySeries($series);
-
throw new CookieTheftException('This token was already used. The account is possibly compromised.');
}
@@ -79,7 +99,7 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
}
$series = $persistentToken->getSeries();
- $tokenValue = $this->generateRandomValue();
+ $tokenValue = base64_encode($this->secureRandom->nextBytes(64));
$this->tokenProvider->updateToken($series, $tokenValue, new \DateTime());
$request->attributes->set(self::COOKIE_ATTR_NAME,
new Cookie(
@@ -101,8 +121,8 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
*/
protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token)
{
- $series = $this->generateRandomValue();
- $tokenValue = $this->generateRandomValue();
+ $series = base64_encode($this->secureRandom->nextBytes(64));
+ $tokenValue = base64_encode($this->secureRandom->nextBytes(64));
$this->tokenProvider->createNewToken(
new PersistentToken(
@@ -126,26 +146,4 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
)
);
}
-
- /**
- * Generates a cryptographically strong random value
- *
- * @return string
- */
- protected function generateRandomValue()
- {
- if (function_exists('openssl_random_pseudo_bytes')) {
- $bytes = openssl_random_pseudo_bytes(64, $strong);
-
- if (true === $strong && false !== $bytes) {
- return base64_encode($bytes);
- }
- }
-
- if (null !== $this->logger) {
- $this->logger->warn('Could not produce a cryptographically strong random value. Please install/update the OpenSSL extension.');
- }
-
- return base64_encode(hash('sha512', uniqid(mt_rand(), true), true));
- }
}
diff --git a/Http/RememberMe/ResponseListener.php b/Http/RememberMe/ResponseListener.php
index 6cbdcb3..03c71c7 100644
--- a/Http/RememberMe/ResponseListener.php
+++ b/Http/RememberMe/ResponseListener.php
@@ -12,13 +12,15 @@
namespace Symfony\Component\Security\Http\RememberMe;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Adds remember-me cookies to the Response.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
-class ResponseListener
+class ResponseListener implements EventSubscriberInterface
{
public function onKernelResponse(FilterResponseEvent $event)
{
@@ -29,4 +31,9 @@ class ResponseListener
$response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME));
}
}
+
+ public static function getSubscribedEvents()
+ {
+ return array(KernelEvents::RESPONSE => 'onKernelResponse');
+ }
}
diff --git a/Http/RememberMe/TokenBasedRememberMeServices.php b/Http/RememberMe/TokenBasedRememberMeServices.php
index bd828f2..5a66fe4 100644
--- a/Http/RememberMe/TokenBasedRememberMeServices.php
+++ b/Http/RememberMe/TokenBasedRememberMeServices.php
@@ -43,7 +43,7 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
$user = $this->getUserProvider($class)->loadUserByUsername($username);
} catch (\Exception $ex) {
if (!$ex instanceof AuthenticationException) {
- $ex = new AuthenticationException($ex->getMessage(), null, $ex->getCode(), $ex);
+ $ex = new AuthenticationException($ex->getMessage(), $ex->getCode(), $ex);
}
throw $ex;