remove user provider name

This commit is contained in:
Johannes Schmitt 2010-12-16 22:27:16 +01:00 committed by Fabien Potencier
parent cd64046811
commit df6ffbbf07
17 changed files with 116 additions and 169 deletions

View File

@ -2,28 +2,22 @@
namespace Symfony\Bundle\DoctrineBundle\Security;
use Symfony\Component\Security\User\AccountInterface;
use Symfony\Component\Security\User\UserProviderInterface;
use Symfony\Component\Security\Exception\UnsupportedAccountException;
use Symfony\Component\Security\Exception\UsernameNotFoundException;
class EntityUserProvider implements UserProviderInterface
{
protected $class;
protected $repository;
protected $property;
protected $name;
public function __construct($em, $name, $class, $property = null)
public function __construct($em, $class, $property = null)
{
$this->class = $class;
$this->repository = $em->getRepository($class);
$this->property = $property;
$this->name = $name;
}
/**
* {@inheritDoc}
*/
public function isAggregate()
{
return false;
}
/**
@ -45,14 +39,18 @@ class EntityUserProvider implements UserProviderInterface
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
}
return array($user, $this->name);
return $user;
}
/**
* {@inheritDoc}
*/
public function supports($providerName)
public function reloadUserByAccount(AccountInterface $account)
{
return $this->name === $providerName;
if (!$account instanceof $this->class) {
throw new UnsupportedAccountException(sprintf('Instances of "%s" are not supported.', get_class($account)));
}
return $this->loadUserByUsername((string) $account);
}
}

View File

@ -2,28 +2,22 @@
namespace Symfony\Bundle\DoctrineMongoDBBundle\Security;
use Symfony\Component\Security\User\AccountInterface;
use Symfony\Component\Security\User\UserProviderInterface;
use Symfony\Component\Security\Exception\UnsupportedAccountException;
use Symfony\Component\Security\Exception\UsernameNotFoundException;
class DocumentUserProvider implements UserProviderInterface
{
protected $class;
protected $repository;
protected $property;
protected $name;
public function __construct($em, $name, $class, $property = null)
public function __construct($em, $class, $property = null)
{
$this->class = $class;
$this->repository = $em->getRepository($class);
$this->property = $property;
$this->name = $name;
}
/**
* {@inheritDoc}
*/
public function isAggregate()
{
return false;
}
/**
@ -45,14 +39,18 @@ class DocumentUserProvider implements UserProviderInterface
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
}
return array($user, $this->name);
return $user;
}
/**
* {@inheritDoc}
*/
public function supports($providerName)
public function reloadUserByAccount(AccountInterface $account)
{
return $this->name === $providerName;
if (!$account instanceof $this->class) {
throw new UnsupportedAccountException(sprintf('Instances of "%s" are not supported.', get_class($account)));
}
return $this->loadUserByUsername((string) $account);
}
}

View File

@ -377,7 +377,6 @@ class SecurityExtension extends Extension
->register($name, '%security.user.provider.entity.class%')
->setArguments(array(
new Reference('security.user.entity_manager'),
$name,
$provider['entity']['class'],
isset($provider['entity']['property']) ? $provider['entity']['property'] : null,
));
@ -391,7 +390,6 @@ class SecurityExtension extends Extension
->register($name, '%security.user.provider.document.class%')
->setArguments(array(
new Reference('security.user.document_manager'),
$name,
$provider['document']['class'],
isset($provider['document']['property']) ? $provider['document']['property'] : null,
));
@ -400,10 +398,7 @@ class SecurityExtension extends Extension
}
// In-memory DAO provider
$definition = $container
->register($name, '%security.user.provider.in_memory.class%')
->setArguments(array($name))
;
$definition = $container->register($name, '%security.user.provider.in_memory.class%');
foreach ($this->fixConfig($provider, 'user') as $username => $user) {
if (isset($user['name'])) {
$username = $user['name'];

View File

@ -2,15 +2,17 @@
namespace Symfony\Component\HttpKernel\Security\Firewall;
use Symfony\Component\Security\User\AccountInterface;
use Symfony\Component\Security\Authentication\Token\TokenInterface;
use Symfony\Component\Security\SecurityContext;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\Security\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Exception\UnsupportedAccountException;
use Symfony\Component\Security\SecurityContext;
use Symfony\Component\Security\User\AccountInterface;
/*
* This file is part of the Symfony framework.
@ -128,37 +130,15 @@ class ContextListener implements ListenerInterface
$user = $token->getUser();
if (!$user instanceof AccountInterface) {
return $token;
} else if (0 === strlen($username = (string) $token)) {
return $token;
} else if (null === $providerName = $token->getUserProviderName()) {
return $token;
}
if (null !== $this->logger) {
$this->logger->debug(sprintf('Reloading user from user provider "%s".', $providerName));
$this->logger->debug(sprintf('Reloading user from user provider.'));
}
foreach ($this->userProviders as $provider) {
if (!$provider->isAggregate() && $provider->supports($providerName)) {
try {
$result = $provider->loadUserByUsername($username);
if (!is_array($result) || 2 !== count($result)) {
throw new \RuntimeException('Provider returned an invalid result.');
}
list($cUser, $cProviderName) = $result;
} catch (\Exception $ex) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('An exception occurred while reloading the user: '.$ex->getMessage()));
}
return null;
}
if ($providerName !== $cProviderName) {
throw new \RuntimeException(sprintf('User was loaded from different provider. Requested "%s", Used: "%s"', $providerName, $cProviderName));
}
try {
$cUser = $provider->reloadUserByAccount($user);
$token->setRoles($cUser->getRoles());
$token->setUser($cUser);
@ -168,9 +148,13 @@ class ContextListener implements ListenerInterface
}
return $token;
} catch (UnsupportedAccountException $unsupported) {
} catch (UsernameNotFoundException $notFound) {
return null;
}
}
throw new \RuntimeException(sprintf('There is no user provider named "%s".', $providerName));
throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user)));
}
}
}

View File

@ -78,28 +78,21 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider
{
$user = $token->getUser();
if ($user instanceof AccountInterface) {
return array($user, $token->getUserProviderName());
return $user;
}
$result = null;
try {
$result = $this->userProvider->loadUserByUsername($username);
$user = $this->userProvider->loadUserByUsername($username);
if (!$user instanceof AccountInterface) {
throw new AuthenticationServiceException('The user provider must return an AccountInterface object.');
}
return $user;
} catch (UsernameNotFoundException $notFound) {
throw $notFound;
} catch (\Exception $repositoryProblem) {
throw new AuthenticationServiceException($repositoryProblem->getMessage(), $token, 0, $repositoryProblem);
}
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 $result;
}
}

View File

@ -54,7 +54,17 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
$username = null === $token->getUser() ? 'NONE_PROVIDED' : (string) $token;
try {
$result = $this->retrieveUser($username, $token);
$user = $this->retrieveUser($username, $token);
if (!$user instanceof AccountInterface) {
throw new AuthenticationServiceException('retrieveUser() must return an AccountInterface.');
}
$this->accountChecker->checkPreAuth($user);
$this->checkAuthentication($user, $token);
$this->accountChecker->checkPostAuth($user);
return new UsernamePasswordToken($user, $token->getCredentials(), $user->getRoles());
} catch (UsernameNotFoundException $notFound) {
if ($this->hideUserNotFoundExceptions) {
throw new BadCredentialsException('Bad credentials', 0, $notFound);
@ -62,17 +72,6 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
throw $notFound;
}
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(), $userProviderName, $user->getRoles());
}
/**

View File

@ -26,7 +26,6 @@ abstract class Token implements TokenInterface
protected $roles;
protected $authenticated;
protected $user;
protected $userProviderName;
protected $credentials;
protected $immutable;
@ -166,14 +165,6 @@ abstract class Token implements TokenInterface
}
}
/**
* {@inheritDoc}
*/
public function getUserProviderName()
{
return $this->userProviderName;
}
/**
* {@inheritdoc}
*/
@ -195,7 +186,7 @@ abstract class Token implements TokenInterface
*/
public function serialize()
{
return serialize(array($this->user, $this->userProviderName, $this->credentials, $this->authenticated, $this->roles, $this->immutable));
return serialize(array($this->user, $this->credentials, $this->authenticated, $this->roles, $this->immutable));
}
/**
@ -203,6 +194,6 @@ abstract class Token implements TokenInterface
*/
public function unserialize($serialized)
{
list($this->user, $this->userProviderName, $this->credentials, $this->authenticated, $this->roles, $this->immutable) = unserialize($serialized);
list($this->user, $this->credentials, $this->authenticated, $this->roles, $this->immutable) = unserialize($serialized);
}
}

View File

@ -65,13 +65,6 @@ interface TokenInterface extends \Serializable
*/
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.
*

View File

@ -21,13 +21,12 @@ class UsernamePasswordToken extends Token
/**
* Constructor.
*/
public function __construct($user, $credentials, $userProviderName = null, array $roles = array())
public function __construct($user, $credentials, array $roles = array())
{
parent::__construct($roles);
$this->setUser($user);
$this->credentials = $credentials;
$this->userProviderName = $userProviderName;
parent::setAuthenticated((Boolean) count($roles));
}

View File

@ -0,0 +1,13 @@
<?php
namespace Symfony\Component\Security\Exception;
/**
* This exception is thrown when an account is reloaded from a provider which
* doesn't support the passed implementation of AccountInterface.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class UnsupportedAccountException extends AuthenticationServiceException
{
}

View File

@ -55,6 +55,8 @@ interface AccountInterface
/**
* Removes sensitive data from the user.
*
* @return void
*/
function eraseCredentials();

View File

@ -3,6 +3,7 @@
namespace Symfony\Component\Security\User;
use Symfony\Component\Security\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Exception\UnsupportedAccountException;
/*
* This file is part of the Symfony package.
@ -24,7 +25,6 @@ use Symfony\Component\Security\Exception\UsernameNotFoundException;
class InMemoryUserProvider implements UserProviderInterface
{
protected $users;
protected $name;
/**
* Constructor.
@ -35,7 +35,7 @@ class InMemoryUserProvider implements UserProviderInterface
* @param array $users An array of users
* @param string $name
*/
public function __construct($name, array $users = array())
public function __construct(array $users = array())
{
foreach ($users as $username => $attributes) {
$password = isset($attributes['password']) ? $attributes['password'] : null;
@ -45,8 +45,6 @@ class InMemoryUserProvider implements UserProviderInterface
$this->createUser($user);
}
$this->name = $name;
}
/**
@ -63,14 +61,6 @@ class InMemoryUserProvider implements UserProviderInterface
$this->users[strtolower($user->getUsername())] = $user;
}
/**
* {@inheritDoc}
*/
public function isAggregate()
{
return false;
}
/**
* {@inheritdoc}
*/
@ -82,15 +72,19 @@ class InMemoryUserProvider implements UserProviderInterface
$user = $this->users[strtolower($username)];
return array(new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(),
$user->isCredentialsNonExpired(), $user->isAccountNonLocked()), $this->name);
return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(),
$user->isCredentialsNonExpired(), $user->isAccountNonLocked());
}
/**
* {@inheritDoc}
*/
public function supports($providerName)
public function reloadUserByAccount(AccountInterface $account)
{
return $this->name === $providerName;
if (!$account instanceof User) {
throw new UnsupportedAccountException(sprintf('Instances of "%s" are not supported.', get_class($account)));
}
return $this->loadUserByUsername((string) $account);
}
}

View File

@ -19,34 +19,28 @@ namespace Symfony\Component\Security\User;
*/
interface UserProviderInterface
{
/**
* Whether this provider is an aggregate of user providers
*
* @return Boolean
*/
function isAggregate();
/**
* Loads the user for the given username.
*
* This method must throw UsernameNotFoundException if the user is not
* found.
*
* @param string $username The username
*
* @return array of the form: array(AccountInterface, string) with the
* implementation of AccountInterface, and the name of the provider
* that was used to retrieve it
*
* @throws UsernameNotFoundException if the user is not found
* @param string $username The username
* @return AccountInterface
*/
function loadUserByUsername($username);
/**
* Determines whether this provider supports the given provider name
*
* @param string $providerName
* @return Boolean
* Loads the user for the account interface.
*
* It is up to the implementation if it decides to reload the user data
* from the database, or if it simply merges the passed User into the
* identity map of an entity manager.
*
* @throws UnsupportedAccountException if the account is not supported
* @param AccountInterface $user
* @return AccountInterface
*/
function supports($providerName);
}
function reloadUserByAccount(AccountInterface $user);
}

View File

@ -75,17 +75,13 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
->method('getUser')
->will($this->returnValue($user))
;
$token->expects($this->once())
->method('getUserProviderName')
->will($this->returnValue('foo'))
;
$provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'));
$reflection = new \ReflectionMethod($provider, 'retrieveUser');
$reflection->setAccessible(true);
$result = $reflection->invoke($provider, null, $token);
$this->assertSame(array($user, 'foo'), $result);
$this->assertSame($user, $result);
}
public function testRetrieveUser()
@ -95,14 +91,14 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$userProvider = $this->getMock('Symfony\Component\Security\User\UserProviderInterface');
$userProvider->expects($this->once())
->method('loadUserByUsername')
->will($this->returnValue($result = array($user, 'foo')))
->will($this->returnValue($user))
;
$provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'));
$method = new \ReflectionMethod($provider, 'retrieveUser');
$method->setAccessible(true);
$this->assertSame($result, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
$this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
}
/**
@ -223,7 +219,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
protected function getSupportedToken()
{
return $this->getMock('Symfony\Component\Security\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getUser', 'getUserProviderName'), array(), '', false);
return $this->getMock('Symfony\Component\Security\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getUser'), array(), '', false);
}
protected function getProvider($user = false, $userChecker = false, $passwordEncoder = null)

View File

@ -86,7 +86,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$provider = $this->getProvider($userChecker);
$provider->expects($this->once())
->method('retrieveUser')
->will($this->returnValue(array($this->getMock('Symfony\Component\Security\User\AccountInterface'), 'foo')))
->will($this->returnValue($this->getMock('Symfony\Component\Security\User\AccountInterface')))
;
$provider->authenticate($this->getSupportedToken());
@ -106,7 +106,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$provider = $this->getProvider($userChecker);
$provider->expects($this->once())
->method('retrieveUser')
->will($this->returnValue(array($this->getMock('Symfony\Component\Security\User\AccountInterface'), 'foo')))
->will($this->returnValue($this->getMock('Symfony\Component\Security\User\AccountInterface')))
;
$provider->authenticate($this->getSupportedToken());
@ -120,7 +120,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$provider = $this->getProvider();
$provider->expects($this->once())
->method('retrieveUser')
->will($this->returnValue(array($this->getMock('Symfony\Component\Security\User\AccountInterface'), 'foo')))
->will($this->returnValue($this->getMock('Symfony\Component\Security\User\AccountInterface')))
;
$provider->expects($this->once())
->method('checkAuthentication')
@ -141,7 +141,7 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$provider = $this->getProvider();
$provider->expects($this->once())
->method('retrieveUser')
->will($this->returnValue(array($user, 'foo')))
->will($this->returnValue($user))
;
$token = $this->getSupportedToken();
@ -154,7 +154,6 @@ class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('Symfony\Component\Security\Authentication\Token\UsernamePasswordToken', $authToken);
$this->assertSame($user, $authToken->getUser());
$this->assertSame('foo', $authToken->getUserProviderName());
$this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles());
$this->assertEquals('foo', $authToken->getCredentials());
}

View File

@ -20,7 +20,7 @@ class UsernamePasswordTokenTest extends \PHPUnit_Framework_TestCase
$token = new UsernamePasswordToken('foo', 'bar');
$this->assertFalse($token->isAuthenticated());
$token = new UsernamePasswordToken('foo', 'bar', null, array('ROLE_FOO'));
$token = new UsernamePasswordToken('foo', 'bar', array('ROLE_FOO'));
$this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
$this->assertTrue($token->isAuthenticated());
}

View File

@ -17,7 +17,7 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$provider = new InMemoryUserProvider('foo', array(
$provider = new InMemoryUserProvider(array(
'fabien' => array(
'password' => 'foo',
'enabled' => false,
@ -25,8 +25,7 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
),
));
list($user, $providerName) = $provider->loadUserByUsername('fabien');
$this->assertSame('foo', $providerName);
$user = $provider->loadUserByUsername('fabien');
$this->assertEquals('foo', $user->getPassword());
$this->assertEquals(array('ROLE_USER'), $user->getRoles());
$this->assertFalse($user->isEnabled());
@ -34,10 +33,10 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
public function testCreateUser()
{
$provider = new InMemoryUserProvider('foo');
$provider = new InMemoryUserProvider();
$provider->createUser(new User('fabien', 'foo'));
list($user, $providerName) = $provider->loadUserByUsername('fabien');
$user = $provider->loadUserByUsername('fabien');
$this->assertEquals('foo', $user->getPassword());
}
@ -46,7 +45,7 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
*/
public function testCreateUserAlreadyExist()
{
$provider = new InMemoryUserProvider('foo');
$provider = new InMemoryUserProvider();
$provider->createUser(new User('fabien', 'foo'));
$provider->createUser(new User('fabien', 'foo'));
}
@ -56,7 +55,7 @@ class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
*/
public function testLoadUserByUsernameDoesNotExist()
{
$provider = new InMemoryUserProvider('foo');
$provider = new InMemoryUserProvider();
$provider->loadUserByUsername('fabien');
}
}