Skip to content

Commit

Permalink
[Security] refactored remember-me code
Browse files Browse the repository at this point in the history
  • Loading branch information
schmittjoh committed Mar 11, 2011
1 parent 129d7c7 commit 3d97638
Show file tree
Hide file tree
Showing 14 changed files with 265 additions and 596 deletions.
Expand Up @@ -12,6 +12,8 @@

<parameter key="security.authentication.rememberme.services.persistent.class">Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices</parameter>
<parameter key="security.authentication.rememberme.services.simplehash.class">Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices</parameter>

<parameter key="security.rememberme.response_listener.class">Symfony\Bundle\SecurityBundle\ResponseListener</parameter>
</parameters>

<services>
Expand Down Expand Up @@ -47,6 +49,10 @@
parent="security.authentication.rememberme.services.abstract"
abstract="true">
</service>

<service id="security.rememberme.response_listener" class="%security.rememberme.response_listener.class%">
<tag name="kernel.listener" method="handle" event="core.response"/>
</service>
</services>

</container>
24 changes: 24 additions & 0 deletions src/Symfony/Bundle/SecurityBundle/ResponseListener.php
@@ -0,0 +1,24 @@
<?php

namespace Symfony\Bundle\SecurityBundle;

use Symfony\Component\EventDispatcher\EventInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;

/**
* Adds remember-me cookies to the Response.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ResponseListener
{
public function handle(EventInterface $event)
{
$request = $event->get('request');
if (!$request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) {
return;
}

$event->get('response')->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME));
}
}
Expand Up @@ -27,7 +27,7 @@ interface AuthenticationManagerInterface
*
* @param TokenInterface $token The TokenInterface instance to authenticate
*
* @return TokenInterface An authenticated TokenInterface instance
* @return TokenInterface An authenticated TokenInterface instance, never null
*
* @throws AuthenticationException if the authentication fails
*/
Expand Down
Expand Up @@ -11,7 +11,6 @@

namespace Symfony\Component\Security\Core\Authentication\Token;

use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
Expand All @@ -23,7 +22,6 @@ class RememberMeToken extends AbstractToken
{
private $key;
private $providerKey;
private $persistentToken;

/**
* Constructor.
Expand All @@ -32,7 +30,7 @@ class RememberMeToken extends AbstractToken
* @param string $providerKey
* @param string $key
*/
public function __construct(UserInterface $user, $providerKey, $key, PersistentTokenInterface $persistentToken = null) {
public function __construct(UserInterface $user, $providerKey, $key) {
parent::__construct($user->getRoles());

if (empty($key)) {
Expand All @@ -45,7 +43,6 @@ public function __construct(UserInterface $user, $providerKey, $key, PersistentT

$this->providerKey = $providerKey;
$this->key = $key;
$this->persistentToken = $persistentToken;

$this->setUser($user);
parent::setAuthenticated(true);
Expand All @@ -70,11 +67,6 @@ public function getKey()
return $this->key;
}

public function getPersistentToken()
{
return $this->persistentToken;
}

public function getCredentials()
{
return '';
Expand Down
77 changes: 18 additions & 59 deletions src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
Expand Up @@ -35,7 +35,6 @@ class RememberMeListener implements ListenerInterface
private $rememberMeServices;
private $authenticationManager;
private $logger;
private $lastState;
private $eventDispatcher;

/**
Expand Down Expand Up @@ -63,7 +62,6 @@ public function __construct(SecurityContext $securityContext, RememberMeServices
public function register(EventDispatcherInterface $dispatcher)
{
$dispatcher->connect('core.security', array($this, 'checkCookies'), 0);
$dispatcher->connect('core.response', array($this, 'updateCookies'), 0);

$this->eventDispatcher = $dispatcher;
}
Expand All @@ -73,7 +71,6 @@ public function register(EventDispatcherInterface $dispatcher)
*/
public function unregister(EventDispatcherInterface $dispatcher)
{
$dispatcher->disconnect('core.response', array($this, 'updateCookies'));
}

/**
Expand All @@ -83,74 +80,36 @@ public function unregister(EventDispatcherInterface $dispatcher)
*/
public function checkCookies(EventInterface $event)
{
$this->lastState = null;

if (null !== $this->securityContext->getToken()) {
return;
}

try {
if (null === $token = $this->rememberMeServices->autoLogin($event->get('request'))) {
return;
}

try {
if (null === $token = $this->authenticationManager->authenticate($token)) {
return;
}

$this->securityContext->setToken($token);

if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.interactive_login', array('request' => $event->get('request'), 'token' => $token)));
}

if (null !== $this->logger) {
$this->logger->debug('SecurityContext populated with remember-me token.');
}
$request = $event->get('request');
if (null === $token = $this->rememberMeServices->autoLogin($request)) {
return;
}

$this->lastState = $token;
} catch (AuthenticationException $failed) {
if (null !== $this->logger) {
$this->logger->debug(
'SecurityContext not populated with remember-me token as the'
.' AuthenticationManager rejected the AuthenticationToken returned'
.' by the RememberMeServices: '.$failed->getMessage()
);
}
try {
$token = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($token);

$this->lastState = $failed;
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->notify(new Event($this, 'security.interactive_login', array('request' => $request, 'token' => $token)));
}
} catch (AuthenticationException $cookieInvalid) {
$this->lastState = $cookieInvalid;

if (null !== $this->logger) {
$this->logger->debug('The presented cookie was invalid: '.$cookieInvalid->getMessage());
$this->logger->debug('SecurityContext populated with remember-me token.');
}

// silently ignore everything except a cookie theft exception
if ($cookieInvalid instanceof CookieTheftException) {
throw $cookieInvalid;
} catch (AuthenticationException $failed) {
if (null !== $this->logger) {
$this->logger->debug(
'SecurityContext not populated with remember-me token as the'
.' AuthenticationManager rejected the AuthenticationToken returned'
.' by the RememberMeServices: '.$failed->getMessage()
);
}
}
}

/**
* Update cookies
* @param Event $event
*/
public function updateCookies(EventInterface $event, Response $response)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
return $response;
}

if ($this->lastState instanceof TokenInterface) {
$this->rememberMeServices->loginSuccess($event->get('request'), $response, $this->lastState);
} else if ($this->lastState instanceof AuthenticationException) {
$this->rememberMeServices->loginFail($event->get('request'), $response);
$this->rememberMeServices->loginFail($request);
}

return $response;
}
}

0 comments on commit 3d97638

Please sign in to comment.