diff options
Diffstat (limited to 'Core')
31 files changed, 415 insertions, 115 deletions
diff --git a/Core/Authentication/AuthenticationProviderManager.php b/Core/Authentication/AuthenticationProviderManager.php index a82b9fb..7ca46c0 100644 --- a/Core/Authentication/AuthenticationProviderManager.php +++ b/Core/Authentication/AuthenticationProviderManager.php @@ -11,6 +11,10 @@ namespace Symfony\Component\Security\Core\Authentication; +use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; +use Symfony\Component\Security\Core\Event\AuthenticationEvent; +use Symfony\Component\Security\Core\AuthenticationEvents; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; @@ -22,11 +26,13 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; * instances to authenticate a Token. * * @author Fabien Potencier <fabien@symfony.com> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ class AuthenticationProviderManager implements AuthenticationManagerInterface { private $providers; private $eraseCredentials; + private $eventDispatcher; /** * Constructor. @@ -44,6 +50,11 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface $this->eraseCredentials = (Boolean) $eraseCredentials; } + public function setEventDispatcher(EventDispatcherInterface $dispatcher) + { + $this->eventDispatcher = $dispatcher; + } + /** * {@inheritdoc} */ @@ -77,6 +88,10 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface $result->eraseCredentials(); } + if (null !== $this->eventDispatcher) { + $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result)); + } + return $result; } @@ -84,6 +99,10 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', get_class($token))); } + if (null !== $this->eventDispatcher) { + $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException)); + } + $lastException->setExtraInformation($token); throw $lastException; diff --git a/Core/Authentication/AuthenticationTrustResolver.php b/Core/Authentication/AuthenticationTrustResolver.php index 8ca28fb..9b3ff3d 100644 --- a/Core/Authentication/AuthenticationTrustResolver.php +++ b/Core/Authentication/AuthenticationTrustResolver.php @@ -28,8 +28,6 @@ class AuthenticationTrustResolver implements AuthenticationTrustResolverInterfac * * @param string $anonymousClass * @param string $rememberMeClass - * - * @return void */ public function __construct($anonymousClass, $rememberMeClass) { diff --git a/Core/Authentication/Provider/AuthenticationProviderInterface.php b/Core/Authentication/Provider/AuthenticationProviderInterface.php index c843216..956adf1 100644 --- a/Core/Authentication/Provider/AuthenticationProviderInterface.php +++ b/Core/Authentication/Provider/AuthenticationProviderInterface.php @@ -15,7 +15,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; /** - * AuthenticationProviderInterface is the interface for for all authentication + * AuthenticationProviderInterface is the interface for all authentication * providers. * * Concrete implementations processes specific Token instances. diff --git a/Core/Authentication/Provider/RememberMeAuthenticationProvider.php b/Core/Authentication/Provider/RememberMeAuthenticationProvider.php index b7f3125..4175907 100644 --- a/Core/Authentication/Provider/RememberMeAuthenticationProvider.php +++ b/Core/Authentication/Provider/RememberMeAuthenticationProvider.php @@ -1,12 +1,12 @@ <?php /* - * This file is part of the Symfony framework. + * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; diff --git a/Core/Authentication/Provider/UserAuthenticationProvider.php b/Core/Authentication/Provider/UserAuthenticationProvider.php index 23aa816..32d7971 100644 --- a/Core/Authentication/Provider/UserAuthenticationProvider.php +++ b/Core/Authentication/Provider/UserAuthenticationProvider.php @@ -65,26 +65,34 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter try { $user = $this->retrieveUser($username, $token); - - if (!$user instanceof UserInterface) { - throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.'); + } catch (UsernameNotFoundException $notFound) { + if ($this->hideUserNotFoundExceptions) { + throw new BadCredentialsException('Bad credentials', 0, $notFound); } + throw $notFound; + } + + if (!$user instanceof UserInterface) { + throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.'); + } + + try { $this->userChecker->checkPreAuth($user); $this->checkAuthentication($user, $token); $this->userChecker->checkPostAuth($user); - - $authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles()); - $authenticatedToken->setAttributes($token->getAttributes()); - - return $authenticatedToken; - } catch (UsernameNotFoundException $notFound) { + } catch (BadCredentialsException $e) { if ($this->hideUserNotFoundExceptions) { - throw new BadCredentialsException('Bad credentials', 0, $notFound); + throw new BadCredentialsException('Bad credentials', 0, $e); } - throw $notFound; + throw $e; } + + $authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles()); + $authenticatedToken->setAttributes($token->getAttributes()); + + return $authenticatedToken; } /** diff --git a/Core/Authentication/RememberMe/InMemoryTokenProvider.php b/Core/Authentication/RememberMe/InMemoryTokenProvider.php index 4653900..a15c2b4 100644 --- a/Core/Authentication/RememberMe/InMemoryTokenProvider.php +++ b/Core/Authentication/RememberMe/InMemoryTokenProvider.php @@ -1,12 +1,12 @@ <?php /* - * This file is part of the Symfony framework. + * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; diff --git a/Core/Authentication/RememberMe/PersistentToken.php b/Core/Authentication/RememberMe/PersistentToken.php index d9029f5..88b0413 100644 --- a/Core/Authentication/RememberMe/PersistentToken.php +++ b/Core/Authentication/RememberMe/PersistentToken.php @@ -1,7 +1,5 @@ <?php -namespace Symfony\Component\Security\Core\Authentication\RememberMe; - /* * This file is part of the Symfony package. * @@ -11,6 +9,8 @@ namespace Symfony\Component\Security\Core\Authentication\RememberMe; * file that was distributed with this source code. */ +namespace Symfony\Component\Security\Core\Authentication\RememberMe; + /** * This class is only used by PersistentTokenRememberMeServices internally. * @@ -27,11 +27,11 @@ final class PersistentToken implements PersistentTokenInterface /** * Constructor * - * @param string $class - * @param string $username - * @param string $series - * @param string $tokenValue - * @param DateTime $lastUsed + * @param string $class + * @param string $username + * @param string $series + * @param string $tokenValue + * @param \DateTime $lastUsed */ public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed) { diff --git a/Core/Authentication/RememberMe/PersistentTokenInterface.php b/Core/Authentication/RememberMe/PersistentTokenInterface.php index 327ffe2..6e9d891 100644 --- a/Core/Authentication/RememberMe/PersistentTokenInterface.php +++ b/Core/Authentication/RememberMe/PersistentTokenInterface.php @@ -1,7 +1,5 @@ <?php -namespace Symfony\Component\Security\Core\Authentication\RememberMe; - /* * This file is part of the Symfony package. * @@ -11,6 +9,8 @@ namespace Symfony\Component\Security\Core\Authentication\RememberMe; * file that was distributed with this source code. */ +namespace Symfony\Component\Security\Core\Authentication\RememberMe; + /** * Interface to be implemented by persistent token classes (such as * Doctrine entities representing a remember-me token) diff --git a/Core/Authentication/RememberMe/TokenProviderInterface.php b/Core/Authentication/RememberMe/TokenProviderInterface.php index 7ef60ac..0c6f75e 100644 --- a/Core/Authentication/RememberMe/TokenProviderInterface.php +++ b/Core/Authentication/RememberMe/TokenProviderInterface.php @@ -1,7 +1,5 @@ <?php -namespace Symfony\Component\Security\Core\Authentication\RememberMe; - /* * This file is part of the Symfony package. * @@ -11,6 +9,8 @@ namespace Symfony\Component\Security\Core\Authentication\RememberMe; * file that was distributed with this source code. */ +namespace Symfony\Component\Security\Core\Authentication\RememberMe; + /** * Interface for TokenProviders * @@ -39,9 +39,9 @@ interface TokenProviderInterface /** * Updates the token according to this data. * - * @param string $series - * @param string $tokenValue - * @param DateTime $lastUsed + * @param string $series + * @param string $tokenValue + * @param \DateTime $lastUsed */ public function updateToken($series, $tokenValue, \DateTime $lastUsed); diff --git a/Core/Authentication/Token/AbstractToken.php b/Core/Authentication/Token/AbstractToken.php index 8e008e5..ed6e8de 100644 --- a/Core/Authentication/Token/AbstractToken.php +++ b/Core/Authentication/Token/AbstractToken.php @@ -14,6 +14,8 @@ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\AdvancedUserInterface; +use Symfony\Component\Security\Core\User\EquatableInterface; /** * Base class for Token instances. @@ -96,7 +98,7 @@ abstract class AbstractToken implements TokenInterface if (!$user instanceof UserInterface) { $changed = true; } else { - $changed = !$this->user->equals($user); + $changed = $this->hasUserChanged($user); } } elseif ($user instanceof UserInterface) { $changed = true; @@ -229,4 +231,49 @@ abstract class AbstractToken implements TokenInterface return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles)); } + + private function hasUserChanged(UserInterface $user) + { + if (!($this->user instanceof UserInterface)) { + throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".'); + } + + if ($this->user instanceof EquatableInterface) { + return ! (Boolean) $this->user->isEqualTo($user); + } + + if ($this->user->getPassword() !== $user->getPassword()) { + return true; + } + + if ($this->user->getSalt() !== $user->getSalt()) { + return true; + } + + if ($this->user->getUsername() !== $user->getUsername()) { + return true; + } + + if ($this->user instanceof AdvancedUserInterface && $user instanceof AdvancedUserInterface) { + if ($this->user->isAccountNonExpired() !== $user->isAccountNonExpired()) { + return true; + } + + if ($this->user->isAccountNonLocked() !== $user->isAccountNonLocked()) { + return true; + } + + if ($this->user->isCredentialsNonExpired() !== $user->isCredentialsNonExpired()) { + return true; + } + + if ($this->user->isEnabled() !== $user->isEnabled()) { + return true; + } + } elseif ($this->user instanceof AdvancedUserInterface xor $user instanceof AdvancedUserInterface) { + return true; + } + + return false; + } } diff --git a/Core/Authentication/Token/RememberMeToken.php b/Core/Authentication/Token/RememberMeToken.php index 7ac9e1c..de50e5c 100644 --- a/Core/Authentication/Token/RememberMeToken.php +++ b/Core/Authentication/Token/RememberMeToken.php @@ -52,7 +52,7 @@ class RememberMeToken extends AbstractToken public function setAuthenticated($authenticated) { if ($authenticated) { - throw new \RuntimeException('You cannot set this token to authenticated after creation.'); + throw new \LogicException('You cannot set this token to authenticated after creation.'); } parent::setAuthenticated(false); diff --git a/Core/AuthenticationEvents.php b/Core/AuthenticationEvents.php new file mode 100644 index 0000000..1e0e6ff --- /dev/null +++ b/Core/AuthenticationEvents.php @@ -0,0 +1,19 @@ +<?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\Core; + +final class AuthenticationEvents +{ + const AUTHENTICATION_SUCCESS = 'security.authentication.success'; + + const AUTHENTICATION_FAILURE = 'security.authentication.failure'; +} diff --git a/Core/Authorization/Voter/AuthenticatedVoter.php b/Core/Authorization/Voter/AuthenticatedVoter.php index d750e33..5847e0d 100644 --- a/Core/Authorization/Voter/AuthenticatedVoter.php +++ b/Core/Authorization/Voter/AuthenticatedVoter.php @@ -35,8 +35,6 @@ class AuthenticatedVoter implements VoterInterface * Constructor. * * @param AuthenticationTrustResolverInterface $authenticationTrustResolver - * - * @return void */ public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver) { diff --git a/Core/Encoder/EncoderFactory.php b/Core/Encoder/EncoderFactory.php index 738706a..9429441 100644 --- a/Core/Encoder/EncoderFactory.php +++ b/Core/Encoder/EncoderFactory.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Security\Core\Encoder; -use Symfony\Component\Security\Core\User\UserInterface; - /** * A generic encoder factory implementation * @@ -30,10 +28,10 @@ class EncoderFactory implements EncoderFactoryInterface /** * {@inheritDoc} */ - public function getEncoder(UserInterface $user) + public function getEncoder($user) { foreach ($this->encoders as $class => $encoder) { - if (!$user instanceof $class) { + if ((is_object($user) && !$user instanceof $class) || (!is_object($user) && !is_subclass_of($user, $class) && $user != $class)) { continue; } @@ -44,7 +42,7 @@ class EncoderFactory implements EncoderFactoryInterface return $this->encoders[$class]; } - throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', get_class($user))); + throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user)); } /** diff --git a/Core/Encoder/EncoderFactoryInterface.php b/Core/Encoder/EncoderFactoryInterface.php index 978f907..2b9834b 100644 --- a/Core/Encoder/EncoderFactoryInterface.php +++ b/Core/Encoder/EncoderFactoryInterface.php @@ -23,9 +23,11 @@ interface EncoderFactoryInterface /** * Returns the password encoder to use for the given account. * - * @param UserInterface $user + * @param UserInterface|string $user A UserInterface instance or a class name * - * @return PasswordEncoderInterface never null + * @return PasswordEncoderInterface + * + * @throws \RuntimeException when no password encoder could be found for the user */ - public function getEncoder(UserInterface $user); + public function getEncoder($user); } diff --git a/Core/Encoder/MessageDigestPasswordEncoder.php b/Core/Encoder/MessageDigestPasswordEncoder.php index a5b2c81..a8bd553 100644 --- a/Core/Encoder/MessageDigestPasswordEncoder.php +++ b/Core/Encoder/MessageDigestPasswordEncoder.php @@ -20,6 +20,7 @@ class MessageDigestPasswordEncoder extends BasePasswordEncoder { private $algorithm; private $encodeHashAsBase64; + private $iterations; /** * Constructor. diff --git a/Core/Encoder/PlaintextPasswordEncoder.php b/Core/Encoder/PlaintextPasswordEncoder.php index 21a9a97..c21f3cd 100644 --- a/Core/Encoder/PlaintextPasswordEncoder.php +++ b/Core/Encoder/PlaintextPasswordEncoder.php @@ -20,6 +20,11 @@ class PlaintextPasswordEncoder extends BasePasswordEncoder { private $ignorePasswordCase; + /** + * Constructor. + * + * @param Boolean $ignorePasswordCase Compare password case-insensitive + */ public function __construct($ignorePasswordCase = false) { $this->ignorePasswordCase = $ignorePasswordCase; diff --git a/Core/Event/AuthenticationEvent.php b/Core/Event/AuthenticationEvent.php new file mode 100644 index 0000000..132cea9 --- /dev/null +++ b/Core/Event/AuthenticationEvent.php @@ -0,0 +1,35 @@ +<?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\Core\Event; + +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\EventDispatcher\Event; + +/** + * This is a general purpose authentication event. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class AuthenticationEvent extends Event +{ + private $authenticationToken; + + public function __construct(TokenInterface $token) + { + $this->authenticationToken = $token; + } + + public function getAuthenticationToken() + { + return $this->authenticationToken; + } +} diff --git a/Core/Event/AuthenticationFailureEvent.php b/Core/Event/AuthenticationFailureEvent.php new file mode 100644 index 0000000..6705fc9 --- /dev/null +++ b/Core/Event/AuthenticationFailureEvent.php @@ -0,0 +1,37 @@ +<?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\Core\Event; + +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + +/** + * This event is dispatched on authentication failure. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class AuthenticationFailureEvent extends AuthenticationEvent +{ + private $authenticationException; + + public function __construct(TokenInterface $token, AuthenticationException $ex) + { + parent::__construct($token); + + $this->authenticationException = $ex; + } + + public function getAuthenticationException() + { + return $this->authenticationException; + } +} diff --git a/Core/Exception/CookieTheftException.php b/Core/Exception/CookieTheftException.php index 09ec79e..2ada78d 100644 --- a/Core/Exception/CookieTheftException.php +++ b/Core/Exception/CookieTheftException.php @@ -1,7 +1,5 @@ <?php -namespace Symfony\Component\Security\Core\Exception; - /* * This file is part of the Symfony package. * @@ -11,6 +9,8 @@ namespace Symfony\Component\Security\Core\Exception; * file that was distributed with this source code. */ +namespace Symfony\Component\Security\Core\Exception; + /** * This exception is thrown when the RememberMeServices implementation * detects that a presented cookie has already been used by someone else. diff --git a/Core/Exception/InvalidCsrfTokenException.php b/Core/Exception/InvalidCsrfTokenException.php index 51adb69..4181bac 100644 --- a/Core/Exception/InvalidCsrfTokenException.php +++ b/Core/Exception/InvalidCsrfTokenException.php @@ -1,12 +1,12 @@ <?php /* - * This file is part of the Symfony framework. + * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; diff --git a/Core/Exception/LogoutException.php b/Core/Exception/LogoutException.php new file mode 100644 index 0000000..2bb954f --- /dev/null +++ b/Core/Exception/LogoutException.php @@ -0,0 +1,25 @@ +<?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\Core\Exception; + +/** + * LogoutException is thrown when the account cannot be logged out. + * + * @author Jeremy Mikola <jmikola@gmail.com> + */ +class LogoutException extends \RuntimeException +{ + public function __construct($message = 'Logout Exception', \Exception $previous = null) + { + parent::__construct($message, 403, $previous); + } +} diff --git a/Core/Exception/SessionUnavailableException.php b/Core/Exception/SessionUnavailableException.php index a00a503..519164a 100644 --- a/Core/Exception/SessionUnavailableException.php +++ b/Core/Exception/SessionUnavailableException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\Security\Core\Exception; * * Possible reasons for this are: * - * a) The session timed-out because the user waited too long. + * a) The session timed out because the user waited too long. * b) The user has disabled cookies, and a new session is started on each * request. * diff --git a/Core/SecurityContextInterface.php b/Core/SecurityContextInterface.php index 8fdd453..78d6477 100644 --- a/Core/SecurityContextInterface.php +++ b/Core/SecurityContextInterface.php @@ -1,12 +1,12 @@ <?php /* - * This file is part of the Symfony framework. + * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; @@ -35,8 +35,6 @@ interface SecurityContextInterface * Sets the authentication token. * * @param TokenInterface $token - * - * @return void */ public function setToken(TokenInterface $token = null); diff --git a/Core/User/ChainUserProvider.php b/Core/User/ChainUserProvider.php index 14a0dec..376ba1c 100644 --- a/Core/User/ChainUserProvider.php +++ b/Core/User/ChainUserProvider.php @@ -1,12 +1,12 @@ <?php /* - * This file is part of the Symfony framework. + * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; diff --git a/Core/User/EquatableInterface.php b/Core/User/EquatableInterface.php new file mode 100644 index 0000000..645b77c --- /dev/null +++ b/Core/User/EquatableInterface.php @@ -0,0 +1,37 @@ +<?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\Core\User; + +/** + * EquatableInterface used to test if two objects are equal in security + * and re-authentication context. + * + * @author Dariusz Górecki <darek.krk@gmail.com> + */ +interface EquatableInterface +{ + /** + * The equality comparison should neither be done by referential equality + * nor by comparing identities (i.e. getId() === getId()). + * + * However, you do not need to compare every attribute, but only those that + * are relevant for assessing whether re-authentication is required. + * + * Also implementation should consider that $user instance may implement + * the extended user interface `AdvancedUserInterface`. + * + * @param UserInterface $user + * + * @return Boolean + */ + public function isEqualTo(UserInterface $user); +} diff --git a/Core/User/User.php b/Core/User/User.php index 0106a8a..b378e1b 100644 --- a/Core/User/User.php +++ b/Core/User/User.php @@ -113,44 +113,4 @@ final class User implements AdvancedUserInterface public function eraseCredentials() { } - - /** - * {@inheritDoc} - */ - public function equals(UserInterface $user) - { - if (!$user instanceof User) { - return false; - } - - if ($this->password !== $user->getPassword()) { - return false; - } - - if ($this->getSalt() !== $user->getSalt()) { - return false; - } - - if ($this->username !== $user->getUsername()) { - return false; - } - - if ($this->accountNonExpired !== $user->isAccountNonExpired()) { - return false; - } - - if ($this->accountNonLocked !== $user->isAccountNonLocked()) { - return false; - } - - if ($this->credentialsNonExpired !== $user->isCredentialsNonExpired()) { - return false; - } - - if ($this->enabled !== $user->isEnabled()) { - return false; - } - - return true; - } } diff --git a/Core/User/UserInterface.php b/Core/User/UserInterface.php index ccb6fbd..ed96ca9 100644 --- a/Core/User/UserInterface.php +++ b/Core/User/UserInterface.php @@ -84,19 +84,4 @@ interface UserInterface * @return void */ public function eraseCredentials(); - - /** - * Returns whether or not the given user is equivalent to *this* user. - * - * The equality comparison should neither be done by referential equality - * nor by comparing identities (i.e. getId() === getId()). - * - * However, you do not need to compare every attribute, but only those that - * are relevant for assessing whether re-authentication is required. - * - * @param UserInterface $user - * - * @return Boolean - */ - public function equals(UserInterface $user); } diff --git a/Core/Util/ClassUtils.php b/Core/Util/ClassUtils.php new file mode 100644 index 0000000..7b583a3 --- /dev/null +++ b/Core/Util/ClassUtils.php @@ -0,0 +1,55 @@ +<?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\Core\Util; + +/** + * Class related functionality for objects that + * might or might not be proxy objects at the moment. + * + * @see Doctrine\Common\Util\ClassUtils + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Johannes Schmitt <schmittjoh@gmail.com> + */ +class ClassUtils +{ + /** + * Marker for Proxy class names. + * + * @var string + */ + const MARKER = '__CG__'; + + /** + * Length of the proxy marker + * + * @var int + */ + const MARKER_LENGTH = 6; + + /** + * Gets the real class name of a class name that could be a proxy. + * + * @param string|object + * @return string + */ + public static function getRealClass($object) + { + $class = is_object($object) ? get_class($object) : $object; + + if (false === $pos = strrpos($class, '\\'.self::MARKER.'\\')) { + return $class; + } + + return substr($class, $pos + self::MARKER_LENGTH + 2); + } +} diff --git a/Core/Validator/Constraint/UserPassword.php b/Core/Validator/Constraint/UserPassword.php new file mode 100644 index 0000000..3279e02 --- /dev/null +++ b/Core/Validator/Constraint/UserPassword.php @@ -0,0 +1,27 @@ +<?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\Core\Validator\Constraint; + +use Symfony\Component\Validator\Constraint; + +/** + * @Annotation + */ +class UserPassword extends Constraint +{ + public $message = 'This value should be the user current password.'; + + public function validatedBy() + { + return 'security.validator.user_password'; + } +} diff --git a/Core/Validator/Constraint/UserPasswordValidator.php b/Core/Validator/Constraint/UserPasswordValidator.php new file mode 100644 index 0000000..a54906b --- /dev/null +++ b/Core/Validator/Constraint/UserPasswordValidator.php @@ -0,0 +1,46 @@ +<?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\Core\Validator\Constraint; + +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\SecurityContextInterface; +use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\ConstraintDefinitionException; + +class UserPasswordValidator extends ConstraintValidator +{ + private $securityContext; + private $encoderFactory; + + public function __construct(SecurityContextInterface $securityContext, EncoderFactoryInterface $encoderFactory) + { + $this->securityContext = $securityContext; + $this->encoderFactory = $encoderFactory; + } + + public function validate($password, Constraint $constraint) + { + $user = $this->securityContext->getToken()->getUser(); + + if (!$user instanceof UserInterface) { + throw new ConstraintDefinitionException('The User must extend UserInterface'); + } + + $encoder = $this->encoderFactory->getEncoder($user); + + if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { + $this->context->addViolation($constraint->message); + } + } +} |