From 27f540463a149eeea5f11fcf7c0d301ae752ff4e Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Tue, 21 Dec 2010 16:10:53 +0100 Subject: [PATCH] added generic encoder factory --- .../Security/Factory/FormLoginFactory.php | 4 +- .../Security/Factory/HttpBasicFactory.php | 4 +- .../Security/Factory/HttpDigestFactory.php | 4 +- .../Factory/SecurityFactoryInterface.php | 2 +- .../Security/Factory/X509Factory.php | 2 +- .../DependencyInjection/SecurityExtension.php | 113 ++++++++++++++---- .../Resources/config/security.xml | 13 +- .../Provider/DaoAuthenticationProvider.php | 16 +-- .../Security/Encoder/EncoderFactory.php | 77 ++++++++++++ .../Encoder/EncoderFactoryInterface.php | 30 +++++ .../DaoAuthenticationProviderTest.php | 25 +++- .../Security/Encoder/EncoderFactoryTest.php | 33 +++++ 12 files changed, 271 insertions(+), 52 deletions(-) create mode 100644 src/Symfony/Component/Security/Encoder/EncoderFactory.php create mode 100644 src/Symfony/Component/Security/Encoder/EncoderFactoryInterface.php create mode 100644 tests/Symfony/Tests/Component/Security/Encoder/EncoderFactoryTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/FormLoginFactory.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/FormLoginFactory.php index 846f6cef78..5e29022210 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/FormLoginFactory.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/FormLoginFactory.php @@ -21,12 +21,12 @@ use Symfony\Component\DependencyInjection\Reference; */ class FormLoginFactory implements SecurityFactoryInterface { - public function create(ContainerBuilder $container, $id, $config, $userProvider, $providerIds, $defaultEntryPoint) + public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) { $provider = 'security.authentication.provider.dao.'.$id; $container ->register($provider, '%security.authentication.provider.dao.class%') - ->setArguments(array(new Reference($userProvider), new Reference('security.account_checker'), new Reference('security.encoder.'.$providerIds[$userProvider]))); + ->setArguments(array(new Reference($userProvider), new Reference('security.account_checker'), new Reference('security.encoder_factory'))); ; // listener diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php index e5a3ba8a3a..02d9c47816 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php @@ -21,12 +21,12 @@ use Symfony\Component\DependencyInjection\Reference; */ class HttpBasicFactory implements SecurityFactoryInterface { - public function create(ContainerBuilder $container, $id, $config, $userProvider, $providerIds, $defaultEntryPoint) + public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) { $provider = 'security.authentication.provider.dao.'.$id; $container ->register($provider, '%security.authentication.provider.dao.class%') - ->setArguments(array(new Reference($userProvider), new Reference('security.account_checker'), new Reference('security.encoder.'.$providerIds[$userProvider]))); + ->setArguments(array(new Reference($userProvider), new Reference('security.account_checker'), new Reference('security.encoder_factory'))); ; // listener diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php index 03b0e53f30..96e4bba0f4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php @@ -21,12 +21,12 @@ use Symfony\Component\DependencyInjection\Reference; */ class HttpDigestFactory implements SecurityFactoryInterface { - public function create(ContainerBuilder $container, $id, $config, $userProvider, $providerIds, $defaultEntryPoint) + public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) { $provider = 'security.authentication.provider.dao.'.$id; $container ->register($provider, '%security.authentication.provider.dao.class%') - ->setArguments(array(new Reference($userProvider), new Reference('security.account_checker'), new Reference('security.encoder.'.$providerIds[$userProvider]))); + ->setArguments(array(new Reference($userProvider), new Reference('security.account_checker'), new Reference('security.encoder_factory'))); ; // listener diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php index ab5fb7e778..9130a31874 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php @@ -20,7 +20,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; */ interface SecurityFactoryInterface { - function create(ContainerBuilder $container, $id, $config, $userProvider, $providerIds, $defaultEntryPoint); + function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint); function getPosition(); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/X509Factory.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/X509Factory.php index 17975f101e..a8f931be5c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/X509Factory.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Security/Factory/X509Factory.php @@ -21,7 +21,7 @@ use Symfony\Component\DependencyInjection\Reference; */ class X509Factory implements SecurityFactoryInterface { - public function create(ContainerBuilder $container, $id, $config, $userProvider, $providerIds, $defaultEntryPoint) + public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) { $provider = 'security.authentication.provider.pre_authenticated.'.$id; $container diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/SecurityExtension.php index 930cd4d927..a608a49418 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/SecurityExtension.php @@ -2,6 +2,8 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; +use Symfony\Component\DependencyInjection\Parameter; + use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Resource\FileResource; @@ -128,6 +130,8 @@ class SecurityExtension extends Extension { $providerIds = $this->createUserProviders($config, $container); + $encoders = $this->createEncoders($config, $container); + if (!$firewalls = $this->fixConfig($config, 'firewall')) { return; } @@ -136,7 +140,7 @@ class SecurityExtension extends Extension $definition = $container->getDefinition('security.context_listener'); $arguments = $definition->getArguments(); $userProviders = array(); - foreach (array_keys($providerIds) as $userProviderId) { + foreach ($providerIds as $userProviderId) { $userProviders[] = new Reference($userProviderId); } $arguments[1] = $userProviders; @@ -195,8 +199,7 @@ class SecurityExtension extends Extension if (!$providerIds) { throw new \InvalidArgumentException('You must provide at least one authentication provider.'); } - $keys = array_keys($providerIds); - $defaultProvider = current($keys); + $defaultProvider = reset($providerIds); } // Register listeners @@ -242,7 +245,7 @@ class SecurityExtension extends Extension } // Authentication listeners - list($authListeners, $providers, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $defaultProvider, $providerIds); + list($authListeners, $providers, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $defaultProvider); $listeners = array_merge($listeners, $authListeners); @@ -263,7 +266,7 @@ class SecurityExtension extends Extension return array($matcher, $listeners, $exceptionListener); } - protected function createAuthenticationListeners($container, $id, $firewall, $defaultProvider, $providerIds) + protected function createAuthenticationListeners($container, $id, $firewall, $defaultProvider) { $listeners = array(); $providers = array(); @@ -295,7 +298,7 @@ class SecurityExtension extends Extension if (array_key_exists($key, $firewall)) { $userProvider = isset($firewall[$key]['provider']) ? $this->getUserProviderId($firewall[$key]['provider']) : $defaultProvider; - list($provider, $listener, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $providerIds, $defaultEntryPoint); + list($provider, $listener, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint); $listeners[] = new Reference($listener); $providers[] = new Reference($provider); @@ -327,29 +330,97 @@ class SecurityExtension extends Extension $providerIds = array(); foreach ($providers as $name => $provider) { - list($id, $encoder) = $this->createUserDaoProvider($name, $provider, $container); + $id = $this->createUserDaoProvider($name, $provider, $container); - if (isset($providerIds[$id])) { + if (in_array($id, $providerIds, true)) { throw new \RuntimeException(sprintf('Provider names must be unique. Duplicate entry for %s.', $id)); } - $providerIds[$id] = $encoder; + $providerIds[] = $id; } return $providerIds; } + protected function createEncoders($config, ContainerBuilder $container) + { + $encoders = $this->fixConfig($config, 'encoder'); + if (!$encoders) { + return array(); + } + + $encoderMap = array(); + foreach ($encoders as $class => $encoder) { + $encoderMap = $this->createEncoder($encoderMap, $class, $encoder, $container); + } + + $container + ->getDefinition('security.encoder_factory.generic') + ->setArguments(array($encoderMap)) + ; + } + + protected function createEncoder(array $encoderMap, $accountClass, $config, ContainerBuilder $container) + { + if (is_array($config) && isset($config['class'])) { + $accountClass = $config['class']; + } + + if (empty($accountClass)) { + throw new \RuntimeException('Each encoder needs an account class.'); + } + + // a minimal message digest encoder + if (is_string($config)) { + $encoderMap[$accountClass] = array( + 'class' => new Parameter('security.encoder.digest.class'), + 'arguments' => array($config), + ); + + return $encoderMap; + } + + // a custom encoder service + if (isset($config['id'])) { + $container + ->getDefinition('security.encoder_factory.generic') + ->addMethodCall('addEncoder', array($accountClass, new Reference($config['id']))) + ; + + return $encoderMap; + } + + // a message digest encoder + if (!isset($config['algorithm'])) { + throw new \RuntimeException('"algoritm" must be defined.'); + } + + $arguments = array($config['algorithm']); + + // add optional arguments + if (isset($config['encode-as-base64'])) { + $arguments[1] = $config['encode-as-base64']; + } else { + $arguments[1] = false; + } + + if (isset($config['iterations'])) { + $arguments[2] = $config['iterations']; + } else { + $arguments[2] = 1; + } + + $encoderMap[$accountClass] = array( + 'class' => new Parameter('security.encoder.digest.class'), + 'arguments' => $arguments, + ); + + return $encoderMap; + } + // Parses a tag and returns the id for the related user provider service protected function createUserDaoProvider($name, $provider, ContainerBuilder $container, $master = true) { - // encoder - $encoder = 'plain'; - if (isset($provider['password-encoder'])) { - $encoder = $provider['password-encoder']; - } elseif (isset($provider['password_encoder'])) { - $encoder = $provider['password_encoder']; - } - if (isset($provider['name'])) { $name = $provider['name']; } @@ -362,7 +433,7 @@ class SecurityExtension extends Extension // Existing DAO service provider if (isset($provider['id'])) { - return array($provider['id'], $encoder); + return $provider['id']; } // Chain provider @@ -381,7 +452,7 @@ class SecurityExtension extends Extension isset($provider['entity']['property']) ? $provider['entity']['property'] : null, )); - return array($name, $encoder); + return $name; } // Doctrine Document DAO provider @@ -394,7 +465,7 @@ class SecurityExtension extends Extension isset($provider['document']['property']) ? $provider['document']['property'] : null, )); - return array($name, $encoder); + return $name; } // In-memory DAO provider @@ -429,7 +500,7 @@ class SecurityExtension extends Extension $definition->addMethodCall('createUser', array(new Reference($userId))); } - return array($name, $encoder); + return $name; } protected function getUserProviderId($name) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml index c179b9b403..75aecd0cec 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/security.xml @@ -11,6 +11,7 @@ null + Symfony\Component\Security\Encoder\EncoderFactory Symfony\Component\Security\Encoder\MessageDigestPasswordEncoder Symfony\Component\Security\Encoder\PlaintextPasswordEncoder @@ -87,15 +88,11 @@ - - sha1 + + - - - md5 - - - + + diff --git a/src/Symfony/Component/Security/Authentication/Provider/DaoAuthenticationProvider.php b/src/Symfony/Component/Security/Authentication/Provider/DaoAuthenticationProvider.php index eaf3242ce0..a44584f8eb 100644 --- a/src/Symfony/Component/Security/Authentication/Provider/DaoAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Authentication/Provider/DaoAuthenticationProvider.php @@ -2,11 +2,10 @@ namespace Symfony\Component\Security\Authentication\Provider; +use Symfony\Component\Security\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\User\UserProviderInterface; use Symfony\Component\Security\User\AccountCheckerInterface; use Symfony\Component\Security\User\AccountInterface; -use Symfony\Component\Security\Encoder\PasswordEncoderInterface; -use Symfony\Component\Security\Encoder\PlaintextPasswordEncoder; use Symfony\Component\Security\Exception\UsernameNotFoundException; use Symfony\Component\Security\Exception\AuthenticationServiceException; use Symfony\Component\Security\Exception\BadCredentialsException; @@ -29,7 +28,7 @@ use Symfony\Component\Security\Authentication\Token\UsernamePasswordToken; */ class DaoAuthenticationProvider extends UserAuthenticationProvider { - protected $passwordEncoder; + protected $encoderFactory; protected $userProvider; /** @@ -37,16 +36,13 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider * * @param UserProviderInterface $userProvider A UserProviderInterface instance * @param AccountCheckerInterface $accountChecker An AccountCheckerInterface instance - * @param PasswordEncoderInterface $passwordEncoder A PasswordEncoderInterface instance + * @param EncoderFactoryInterface $encoderFactory A EncoderFactoryInterface instance */ - public function __construct(UserProviderInterface $userProvider, AccountCheckerInterface $accountChecker, PasswordEncoderInterface $passwordEncoder = null, $hideUserNotFoundExceptions = true) + public function __construct(UserProviderInterface $userProvider, AccountCheckerInterface $accountChecker, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true) { parent::__construct($accountChecker, $hideUserNotFoundExceptions); - if (null === $passwordEncoder) { - $passwordEncoder = new PlaintextPasswordEncoder(); - } - $this->passwordEncoder = $passwordEncoder; + $this->encoderFactory = $encoderFactory; $this->userProvider = $userProvider; } @@ -65,7 +61,7 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider throw new BadCredentialsException('Bad credentials'); } - if (!$this->passwordEncoder->isPasswordValid($account->getPassword(), $presentedPassword, $account->getSalt())) { + if (!$this->encoderFactory->getEncoder($account)->isPasswordValid($account->getPassword(), $presentedPassword, $account->getSalt())) { throw new BadCredentialsException('Bad credentials'); } } diff --git a/src/Symfony/Component/Security/Encoder/EncoderFactory.php b/src/Symfony/Component/Security/Encoder/EncoderFactory.php new file mode 100644 index 0000000000..5462ac2759 --- /dev/null +++ b/src/Symfony/Component/Security/Encoder/EncoderFactory.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * A generic encoder factory implementation + * + * @author Johannes M. Schmitt + */ +class EncoderFactory implements EncoderFactoryInterface +{ + protected $encoders; + protected $encoderMap; + + public function __construct(array $encoderMap) + { + $this->encoders = array(); + $this->encoderMap = $encoderMap; + } + + /** + * {@inheritDoc} + */ + public function getEncoder(AccountInterface $account) + { + foreach ($this->encoders as $class => $encoder) { + if ($account instanceof $class) { + return $encoder; + } + } + + return $this->createEncoder($account); + } + + /** + * Adds an encoder instance to the factory + * + * @param string $class + * @param PasswordEncoderInterface $encoder + * @return void + */ + public function addEncoder($class, PasswordEncoderInterface $encoder) + { + $this->encoders[$class] = $encoder; + } + + /** + * Creates the actual encoder instance + * + * @param AccountInterface $account + * @return PasswordEncoderInterface + */ + protected function createEncoder($account) + { + foreach ($this->encoderMap as $class => $config) { + if ($account instanceof $class) { + $reflection = new \ReflectionClass($config['class']); + $this->encoders[$class] = $reflection->newInstanceArgs($config['arguments']); + + return $this->encoders[$class]; + } + } + + throw new \InvalidArgumentException(sprintf('No encoder has been configured for account "%s".', get_class($account))); + } +} \ No newline at end of file diff --git a/src/Symfony/Component/Security/Encoder/EncoderFactoryInterface.php b/src/Symfony/Component/Security/Encoder/EncoderFactoryInterface.php new file mode 100644 index 0000000000..0c62b35e04 --- /dev/null +++ b/src/Symfony/Component/Security/Encoder/EncoderFactoryInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * EncoderFactoryInterface to support different encoders for different accounts. + * + * @author Johannes M. Schmitt + */ +interface EncoderFactoryInterface +{ + /** + * Returns the password encoder to use for the given account + * + * @param AccountInterface $account + * @return PasswordEncoderInterface never null + */ + function getEncoder(AccountInterface $account); +} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/Security/Authentication/Provider/DaoAuthenticationProviderTest.php b/tests/Symfony/Tests/Component/Security/Authentication/Provider/DaoAuthenticationProviderTest.php index adc704dce7..2658e617e1 100644 --- a/tests/Symfony/Tests/Component/Security/Authentication/Provider/DaoAuthenticationProviderTest.php +++ b/tests/Symfony/Tests/Component/Security/Authentication/Provider/DaoAuthenticationProviderTest.php @@ -10,6 +10,10 @@ namespace Symfony\Tests\Component\Security\Authentication\Provider; +use Symfony\Component\Security\Encoder\EncoderFactory; + +use Symfony\Component\Security\Encoder\PlaintextPasswordEncoder; + use Symfony\Component\Security\Authentication\Provider\DaoAuthenticationProvider; class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase @@ -37,7 +41,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\UsernameNotFoundException', null, array(), '', false))) ; - $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface')); + $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'), $this->getMock('Symfony\Component\Security\Encoder\EncoderFactoryInterface')); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); @@ -55,7 +59,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase ->will($this->throwException($this->getMock('RuntimeException', null, array(), '', false))) ; - $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface')); + $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'), $this->getMock('Symfony\Component\Security\Encoder\EncoderFactoryInterface')); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); @@ -76,7 +80,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($user)) ; - $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface')); + $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'), $this->getMock('Symfony\Component\Security\Encoder\EncoderFactoryInterface')); $reflection = new \ReflectionMethod($provider, 'retrieveUser'); $reflection->setAccessible(true); $result = $reflection->invoke($provider, null, $token); @@ -94,7 +98,7 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($user)) ; - $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface')); + $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'), $this->getMock('Symfony\Component\Security\Encoder\EncoderFactoryInterface')); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); @@ -236,6 +240,17 @@ class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase $userChecker = $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'); } - return new DaoAuthenticationProvider($userProvider, $userChecker, $passwordEncoder); + if (null === $passwordEncoder) { + $passwordEncoder = new PlaintextPasswordEncoder(); + } + + $encoderFactory = $this->getMock('Symfony\Component\Security\Encoder\EncoderFactoryInterface'); + $encoderFactory + ->expects($this->any()) + ->method('getEncoder') + ->will($this->returnValue($passwordEncoder)) + ; + + return new DaoAuthenticationProvider($userProvider, $userChecker, $encoderFactory); } } diff --git a/tests/Symfony/Tests/Component/Security/Encoder/EncoderFactoryTest.php b/tests/Symfony/Tests/Component/Security/Encoder/EncoderFactoryTest.php new file mode 100644 index 0000000000..51a8a8d261 --- /dev/null +++ b/tests/Symfony/Tests/Component/Security/Encoder/EncoderFactoryTest.php @@ -0,0 +1,33 @@ + array( + 'class' => 'Symfony\Component\Security\Encoder\MessageDigestPasswordEncoder', + 'arguments' => array('sha512', true, 5), + ))); + + $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\User\AccountInterface')); + $expectedEncoder = new MessageDigestPasswordEncoder('sha512', true, 5); + + $this->assertEquals($expectedEncoder->encodePassword('foo', 'moo'), $encoder->encodePassword('foo', 'moo')); + } + + public function testGetEncoderWithService() + { + $factory = new EncoderFactory(array()); + $factory->addEncoder('Symfony\Component\Security\User\AccountInterface', new MessageDigestPasswordEncoder('sha1')); + + $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\User\AccountInterface')); + $expectedEncoder = new MessageDigestPasswordEncoder('sha1'); + + $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', '')); + } +} \ No newline at end of file