diff options
author | Johannes Schmitt <schmittjoh@gmail.com> | 2010-12-08 13:51:26 +0100 |
---|---|---|
committer | Fabien Potencier <fabien.potencier@gmail.com> | 2010-12-15 17:38:30 +0100 |
commit | a77e6b5f60bd1dac4d7ba19a900d72ae45d9fe26 (patch) | |
tree | a594a87afbc527dcc458d18558cf5bea3f08b1e9 /Authentication | |
parent | b8fc4a14f4cff6bb490cf04422716a2949b6f3bc (diff) | |
download | symfony-security-a77e6b5f60bd1dac4d7ba19a900d72ae45d9fe26.zip symfony-security-a77e6b5f60bd1dac4d7ba19a900d72ae45d9fe26.tar.gz symfony-security-a77e6b5f60bd1dac4d7ba19a900d72ae45d9fe26.tar.bz2 |
fixed user refreshing after unserialization
Diffstat (limited to 'Authentication')
-rw-r--r-- | Authentication/Provider/DaoAuthenticationProvider.php | 36 | ||||
-rw-r--r-- | Authentication/Provider/UserAuthenticationProvider.php | 11 | ||||
-rw-r--r-- | Authentication/Token/Token.php | 74 | ||||
-rw-r--r-- | Authentication/Token/TokenInterface.php | 47 | ||||
-rw-r--r-- | Authentication/Token/UsernamePasswordToken.php | 5 |
5 files changed, 138 insertions, 35 deletions
diff --git a/Authentication/Provider/DaoAuthenticationProvider.php b/Authentication/Provider/DaoAuthenticationProvider.php index 9a9f857..34880b2 100644 --- a/Authentication/Provider/DaoAuthenticationProvider.php +++ b/Authentication/Provider/DaoAuthenticationProvider.php @@ -55,12 +55,19 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider */ protected function checkAuthentication(AccountInterface $account, UsernamePasswordToken $token) { - if (!$presentedPassword = (string) $token->getCredentials()) { - throw new BadCredentialsException('Bad credentials'); - } + $user = $token->getUser(); + if ($user instanceof AccountInterface) { + if ($account->getPassword() !== $user->getPassword()) { + throw new BadCredentialsException('The credentials were changed from another session.'); + } + } else { + if (!$presentedPassword = (string) $token->getCredentials()) { + throw new BadCredentialsException('Bad credentials'); + } - if (!$this->passwordEncoder->isPasswordValid($account->getPassword(), $presentedPassword, $account->getSalt())) { - throw new BadCredentialsException('Bad credentials'); + if (!$this->passwordEncoder->isPasswordValid($account->getPassword(), $presentedPassword, $account->getSalt())) { + throw new BadCredentialsException('Bad credentials'); + } } } @@ -69,19 +76,30 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider */ protected function retrieveUser($username, UsernamePasswordToken $token) { - $user = null; + $user = $token->getUser(); + if ($user instanceof AccountInterface) { + return array($user, $token->getUserProviderName()); + } + + $result = null; try { - $user = $this->userProvider->loadUserByUsername($username); + $result = $this->userProvider->loadUserByUsername($username); } catch (UsernameNotFoundException $notFound) { throw $notFound; } catch (\Exception $repositoryProblem) { throw new AuthenticationServiceException($repositoryProblem->getMessage(), $token, 0, $repositoryProblem); } - if (!$user instanceof AccountInterface) { + if (!is_array($result) || 2 !== count($result)) { + throw new AuthenticationServiceException('User provider did not return an array, or array had invalid format.'); + } + if (!$result[0] instanceof AccountInterface) { throw new AuthenticationServiceException('The user provider must return an AccountInterface object.'); } + if (empty($result[1])) { + throw new AuthenticationServiceException('The user provider must return a non-empty user provider name.'); + } - return $user; + return $result; } } diff --git a/Authentication/Provider/UserAuthenticationProvider.php b/Authentication/Provider/UserAuthenticationProvider.php index 60c58c1..f621e42 100644 --- a/Authentication/Provider/UserAuthenticationProvider.php +++ b/Authentication/Provider/UserAuthenticationProvider.php @@ -54,7 +54,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter $username = null === $token->getUser() ? 'NONE_PROVIDED' : (string) $token; try { - $user = $this->retrieveUser($username, $token); + $result = $this->retrieveUser($username, $token); } catch (UsernameNotFoundException $notFound) { if ($this->hideUserNotFoundExceptions) { throw new BadCredentialsException('Bad credentials', 0, $notFound); @@ -63,15 +63,16 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter throw $notFound; } - if (!$user instanceof AccountInterface) { - throw new AuthenticationServiceException('The retrieveUser() methods must return an AccountInterface object.'); + if (!is_array($result) || 2 !== count($result)) { + throw new AuthenticationServiceException('retrieveUser() did not return an array, or array had invalid format.'); } + list($user, $userProviderName) = $result; $this->accountChecker->checkPreAuth($user); $this->checkAuthentication($user, $token); $this->accountChecker->checkPostAuth($user); - return new UsernamePasswordToken($user, $token->getCredentials(), $user->getRoles()); + return new UsernamePasswordToken($user, $token->getCredentials(), $userProviderName, $user->getRoles()); } /** @@ -88,7 +89,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter * @param string $username The username to retrieve * @param UsernamePasswordToken $token The Token * - * @return AccountInterface The user + * @return array The user * * @throws AuthenticationException if the credentials could not be validated */ diff --git a/Authentication/Token/Token.php b/Authentication/Token/Token.php index 808f151..37b7ded 100644 --- a/Authentication/Token/Token.php +++ b/Authentication/Token/Token.php @@ -19,12 +19,14 @@ use Symfony\Component\Security\User\AccountInterface; * Base class for Token instances. * * @author Fabien Potencier <fabien.potencier@symfony-project.com> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ abstract class Token implements TokenInterface { protected $roles; protected $authenticated; protected $user; + protected $userProviderName; protected $credentials; protected $immutable; @@ -35,13 +37,7 @@ abstract class Token implements TokenInterface */ public function __construct(array $roles = array()) { - $this->roles = array(); - foreach ($roles as $role) { - if (is_string($role)) { - $role = new Role((string) $role); - } - $this->addRole($role); - } + $this->setRoles($roles); $this->authenticated = false; $this->immutable = false; } @@ -53,6 +49,10 @@ abstract class Token implements TokenInterface */ public function addRole(RoleInterface $role) { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + $this->roles[] = $role; } @@ -65,6 +65,22 @@ abstract class Token implements TokenInterface } /** + * {@inheritDoc} + */ + public function setRoles(array $roles) + { + $this->roles = array(); + + foreach ($roles as $role) { + if (is_string($role)) { + $role = new Role($role); + } + + $this->addRole($role); + } + } + + /** * {@inheritdoc} */ public function __toString() @@ -91,6 +107,10 @@ abstract class Token implements TokenInterface */ public function setAuthenticated($authenticated) { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + $this->authenticated = (Boolean) $authenticated; } @@ -111,10 +131,32 @@ abstract class Token implements TokenInterface } /** + * {@inheritDoc} + */ + public function setUser($user) + { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + + if (!is_string($user) && !is_object($user)) { + throw new \InvalidArgumentException('$user must be an object, or a primitive string.'); + } else if (is_object($user) && !method_exists($user, '__toString')) { + throw new \InvalidArgumentException('If $user is an object, it must implement __toString().'); + } + + $this->user = $user; + } + + /** * {@inheritdoc} */ public function eraseCredentials() { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + if ($this->getCredentials() instanceof AccountInterface) { $this->getCredentials()->eraseCredentials(); } @@ -125,6 +167,14 @@ abstract class Token implements TokenInterface } /** + * {@inheritDoc} + */ + public function getUserProviderName() + { + return $this->userProviderName; + } + + /** * {@inheritdoc} */ public function isImmutable() @@ -135,9 +185,9 @@ abstract class Token implements TokenInterface /** * {@inheritdoc} */ - public function setImmutable($value) + public function setImmutable() { - $this->immutable = (Boolean) $value; + $this->immutable = true; } /** @@ -145,9 +195,7 @@ abstract class Token implements TokenInterface */ public function serialize() { - // FIXME: don't serialize the user object, just the username (see ContextListener) - //return serialize(array((string) $this, $this->credentials, $this->authenticated, $this->roles, $this->immutable)); - return serialize(array($this->user, $this->credentials, $this->authenticated, $this->roles, $this->immutable)); + return serialize(array($this->user, $this->userProviderName, $this->credentials, $this->authenticated, $this->roles, $this->immutable)); } /** @@ -155,6 +203,6 @@ abstract class Token implements TokenInterface */ public function unserialize($serialized) { - list($this->user, $this->credentials, $this->authenticated, $this->roles, $this->immutable) = unserialize($serialized); + list($this->user, $this->userProviderName, $this->credentials, $this->authenticated, $this->roles, $this->immutable) = unserialize($serialized); } } diff --git a/Authentication/Token/TokenInterface.php b/Authentication/Token/TokenInterface.php index 01753cf..4f37522 100644 --- a/Authentication/Token/TokenInterface.php +++ b/Authentication/Token/TokenInterface.php @@ -2,6 +2,8 @@ namespace Symfony\Component\Security\Authentication\Token; +use Symfony\Component\Security\User\AccountInterface; + /* * This file is part of the Symfony package. * @@ -33,6 +35,14 @@ interface TokenInterface extends \Serializable function getRoles(); /** + * Sets the user's roles + * + * @param array $roles + * @return void + */ + function setRoles(array $roles); + + /** * Returns the user credentials. * * @return mixed The user credentials @@ -40,18 +50,27 @@ interface TokenInterface extends \Serializable function getCredentials(); /** - * Checks whether the token is immutable or not. + * Returns a user representation. * - * @return Boolean true if the token is immutable, false otherwise + * @return mixed either returns an object which implements __toString(), or + * a primitive string is returned. */ - function isImmutable(); + function getUser(); /** - * Returns a user instance. + * Sets the user. * - * @return object The User instance + * @param mixed $user can either be an object which implements __toString(), or + * only a primitive string */ - function getUser(); + function setUser($user); + + /** + * Returns a unique id for the user provider that was used to retrieve the user + * + * @return string + */ + function getUserProviderName(); /** * Checks if the user is authenticated or not. @@ -68,6 +87,22 @@ interface TokenInterface extends \Serializable function setAuthenticated($isAuthenticated); /** + * Whether this token is considered immutable + * + * @return Boolean + */ + function isImmutable(); + + /** + * Marks this token as immutable. This change cannot be reversed. + * + * You'll need to create a new token if you want a mutable token again. + * + * @return void + */ + function setImmutable(); + + /** * Removes sensitive information from the token. */ function eraseCredentials(); diff --git a/Authentication/Token/UsernamePasswordToken.php b/Authentication/Token/UsernamePasswordToken.php index ae248e8..ce11cb3 100644 --- a/Authentication/Token/UsernamePasswordToken.php +++ b/Authentication/Token/UsernamePasswordToken.php @@ -21,12 +21,13 @@ class UsernamePasswordToken extends Token /** * Constructor. */ - public function __construct($user, $credentials, array $roles = array()) + public function __construct($user, $credentials, $userProviderName = null, array $roles = array()) { parent::__construct($roles); - $this->user = $user; + $this->setUser($user); $this->credentials = $credentials; + $this->userProviderName = $userProviderName; parent::setAuthenticated((Boolean) count($roles)); } |