/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php

https://github.com/Kiruban2011/symfony · PHP · 152 lines · 97 code · 21 blank · 34 comment · 9 complexity · a0912b48a85481bf202b9225925c9025 MD5 · raw file

  1. <?php
  2. namespace Symfony\Component\Security\Http\RememberMe;
  3. use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
  4. use Symfony\Component\HttpFoundation\Cookie;
  5. use Symfony\Component\HttpFoundation\Response;
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  8. use Symfony\Component\Security\Core\Exception\CookieTheftException;
  9. use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
  12. /*
  13. * This file is part of the Symfony package.
  14. *
  15. * (c) Fabien Potencier <fabien@symfony.com>
  16. *
  17. * For the full copyright and license information, please view the LICENSE
  18. * file that was distributed with this source code.
  19. */
  20. /**
  21. * Concrete implementation of the RememberMeServicesInterface which needs
  22. * an implementation of TokenProviderInterface for providing remember-me
  23. * capabilities.
  24. *
  25. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  26. */
  27. class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
  28. {
  29. private $tokenProvider;
  30. /**
  31. * Sets the token provider
  32. *
  33. * @param TokenProviderInterface $tokenProvider
  34. */
  35. public function setTokenProvider(TokenProviderInterface $tokenProvider)
  36. {
  37. $this->tokenProvider = $tokenProvider;
  38. }
  39. /**
  40. * {@inheritDoc}
  41. */
  42. public function logout(Request $request, Response $response, TokenInterface $token)
  43. {
  44. parent::logout($request, $response, $token);
  45. if (null !== ($cookie = $request->cookies->get($this->options['name']))
  46. && count($parts = $this->decodeCookie($cookie)) === 2
  47. ) {
  48. list($series, $tokenValue) = $parts;
  49. $this->tokenProvider->deleteTokenBySeries($series);
  50. }
  51. }
  52. /**
  53. * {@inheritDoc}
  54. */
  55. protected function processAutoLoginCookie(array $cookieParts, Request $request)
  56. {
  57. if (count($cookieParts) !== 2) {
  58. throw new AuthenticationException('The cookie is invalid.');
  59. }
  60. list($series, $tokenValue) = $cookieParts;
  61. $persistentToken = $this->tokenProvider->loadTokenBySeries($series);
  62. if ($persistentToken->getTokenValue() !== $tokenValue) {
  63. $this->tokenProvider->deleteTokenBySeries($series);
  64. throw new CookieTheftException('This token was already used. The account is possibly compromised.');
  65. }
  66. if ($persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'] < time()) {
  67. throw new AuthenticationException('The cookie has expired.');
  68. }
  69. $series = $persistentToken->getSeries();
  70. $tokenValue = $this->generateRandomValue();
  71. $this->tokenProvider->updateToken($series, $tokenValue, new \DateTime());
  72. $request->attributes->set(self::COOKIE_ATTR_NAME,
  73. new Cookie(
  74. $this->options['name'],
  75. $this->encodeCookie(array($series, $tokenValue)),
  76. time() + $this->options['lifetime'],
  77. $this->options['path'],
  78. $this->options['domain'],
  79. $this->options['secure'],
  80. $this->options['httponly']
  81. )
  82. );
  83. return $this->getUserProvider($persistentToken->getClass())->loadUserByUsername($persistentToken->getUsername());
  84. }
  85. /**
  86. * {@inheritDoc}
  87. */
  88. protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token)
  89. {
  90. $series = $this->generateRandomValue();
  91. $tokenValue = $this->generateRandomValue();
  92. $this->tokenProvider->createNewToken(
  93. new PersistentToken(
  94. get_class($user = $token->getUser()),
  95. $user->getUsername(),
  96. $series,
  97. $tokenValue,
  98. new \DateTime()
  99. )
  100. );
  101. $response->headers->setCookie(
  102. new Cookie(
  103. $this->options['name'],
  104. $this->encodeCookie(array($series, $tokenValue)),
  105. time() + $this->options['lifetime'],
  106. $this->options['path'],
  107. $this->options['domain'],
  108. $this->options['secure'],
  109. $this->options['httponly']
  110. )
  111. );
  112. }
  113. /**
  114. * Generates a cryptographically strong random value
  115. *
  116. * @return string
  117. */
  118. protected function generateRandomValue()
  119. {
  120. if (function_exists('openssl_random_pseudo_bytes')) {
  121. $bytes = openssl_random_pseudo_bytes(64, $strong);
  122. if (true === $strong && false !== $bytes) {
  123. return base64_encode($bytes);
  124. }
  125. }
  126. if (null !== $this->logger) {
  127. $this->logger->warn('Could not produce a cryptographically strong random value. Please install/update the OpenSSL extension.');
  128. }
  129. return base64_encode(hash('sha512', uniqid(mt_rand(), true), true));
  130. }
  131. }