diff options
author | Johannes M. Schmitt <schmittjoh@gmail.com> | 2011-01-26 21:34:11 +0100 |
---|---|---|
committer | Fabien Potencier <fabien.potencier@gmail.com> | 2011-01-26 22:23:20 +0100 |
commit | bebc09870cb0a7720e2c6a8c5c74585e69e8bb24 (patch) | |
tree | 0c399647cdbe504be405017e7cc04c70c53482f2 /Http/RememberMe/PersistentTokenBasedRememberMeServices.php | |
parent | c85f3d708d2c9b00d73ca1234ccfaf50336d94b1 (diff) | |
download | symfony-security-bebc09870cb0a7720e2c6a8c5c74585e69e8bb24.zip symfony-security-bebc09870cb0a7720e2c6a8c5c74585e69e8bb24.tar.gz symfony-security-bebc09870cb0a7720e2c6a8c5c74585e69e8bb24.tar.bz2 |
namespace changes
Symfony\Component\Security -> Symfony\Component\Security\Core
Symfony\Component\Security\Acl remains unchanged
Symfony\Component\HttpKernel\Security -> Symfony\Component\Security\Http
Diffstat (limited to 'Http/RememberMe/PersistentTokenBasedRememberMeServices.php')
-rw-r--r-- | Http/RememberMe/PersistentTokenBasedRememberMeServices.php | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php new file mode 100644 index 0000000..73e5863 --- /dev/null +++ b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -0,0 +1,165 @@ +<?php + +namespace Symfony\Component\Security\Http\RememberMe; + +use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Request; +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\Authentication\Token\RememberMeToken; + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Concrete implementation of the RememberMeServicesInterface which needs + * an implementation of TokenProviderInterface for providing remember-me + * capabilities. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class PersistentTokenBasedRememberMeServices extends RememberMeServices +{ + protected $tokenProvider; + + /** + * Sets the token provider + * + * @param TokenProviderInterface $tokenProvider + * @return void + */ + public function setTokenProvider(TokenProviderInterface $tokenProvider) + { + $this->tokenProvider = $tokenProvider; + } + + /** + * {@inheritDoc} + */ + protected function processAutoLoginCookie(array $cookieParts, Request $request) + { + if (count($cookieParts) !== 2) { + throw new AuthenticationException('The cookie is invalid.'); + } + + list($series, $tokenValue) = $cookieParts; + $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.'); + } + + if ($persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'] < time()) { + throw new AuthenticationException('The cookie has expired.'); + } + + $user = $this->getUserProvider($persistentToken->getClass())->loadUserByUsername($persistentToken->getUsername()); + $authenticationToken = new RememberMeToken($user, $this->providerKey, $this->key); + $authenticationToken->setPersistentToken($persistentToken); + + return $authenticationToken; + } + + /** + * {@inheritDoc} + */ + protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token) + { + if ($token instanceof RememberMeToken) { + if (null === $persistentToken = $token->getPersistentToken()) { + throw new \RuntimeException('RememberMeToken must contain a PersistentTokenInterface implementation when used as login.'); + } + + $series = $persistentToken->getSeries(); + $tokenValue = $this->generateRandomValue(); + + $this->tokenProvider->updateToken($series, $tokenValue, new \DateTime()); + } else { + $series = $this->generateRandomValue(); + $tokenValue = $this->generateRandomValue(); + + $this->tokenProvider->createNewToken( + new PersistentToken( + get_class($user = $token->getUser()), + $user->getUsername(), + $series, + $tokenValue, + new \DateTime() + ) + ); + } + + $response->headers->setCookie( + new Cookie( + $this->options['name'], + $this->generateCookieValue($series, $tokenValue), + time() + $this->options['lifetime'], + $this->options['path'], + $this->options['domain'], + $this->options['secure'], + $this->options['httponly'] + ) + ); + } + + /** + * {@inheritDoc} + */ + public function logout(Request $request, Response $response, TokenInterface $token) + { + parent::logout($request, $response, $token); + + if (null !== ($cookie = $request->cookies->get($this->options['name'])) + && count($parts = $this->decodeCookie($cookie)) === 2 + ) { + list($series, $tokenValue) = $parts; + $this->tokenProvider->deleteTokenBySeries($series); + } + } + + /** + * Generates the value for the cookie + * + * @param string $series + * @param string $tokenValue + * @return string + */ + protected function generateCookieValue($series, $tokenValue) + { + return $this->encodeCookie(array($series, $tokenValue)); + } + + /** + * Generates a cryptographically strong random value + * + * @return string + */ + protected function generateRandomValue() + { + if (function_exists('openssl_random_pseudo_bytes')) { + $bytes = openssl_random_pseudo_bytes(32, $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('sha256', uniqid(mt_rand(), true), true)); + } +} |