feature #10005 [Security] Added named encoders to EncoderFactory (tamirvs)
This PR was squashed before being merged into the 2.5-dev branch (closes #10005).
Discussion
----------
[Security] Added named encoders to EncoderFactory
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #9743
| License | MIT
| Doc PR | -
This PR is basically merging FOSAdvancedEncoder. I think it's better than having a separate bundle that most of it's code is a copy of the core.
A use case is: having a different encoders or bcrypt cost based on the user's roles.
Commits
-------
c69e2ca
[Security] Added named encoders to EncoderFactory
This commit is contained in:
commit
4ad343bd0f
@ -0,0 +1,28 @@
|
||||
<?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\Encoder;
|
||||
|
||||
/**
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*/
|
||||
interface EncoderAwareInterface
|
||||
{
|
||||
/**
|
||||
* Gets the name of the encoder used to encode the password.
|
||||
*
|
||||
* If the method returns null, the standard way to retrieve the encoder
|
||||
* will be used instead.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEncoderName();
|
||||
}
|
@ -30,19 +30,32 @@ class EncoderFactory implements EncoderFactoryInterface
|
||||
*/
|
||||
public function getEncoder($user)
|
||||
{
|
||||
foreach ($this->encoders as $class => $encoder) {
|
||||
if ((is_object($user) && !$user instanceof $class) || (!is_object($user) && !is_subclass_of($user, $class) && $user != $class)) {
|
||||
continue;
|
||||
$encoderKey = null;
|
||||
|
||||
if ($user instanceof EncoderAwareInterface && (null !== $encoderName = $user->getEncoderName())) {
|
||||
if (!array_key_exists($encoderName, $this->encoders)) {
|
||||
throw new \RuntimeException(sprintf('The encoder "%s" was not configured.', $encoderName));
|
||||
}
|
||||
|
||||
if (!$encoder instanceof PasswordEncoderInterface) {
|
||||
return $this->encoders[$class] = $this->createEncoder($encoder);
|
||||
$encoderKey = $encoderName;
|
||||
} else {
|
||||
foreach ($this->encoders as $class => $encoder) {
|
||||
if ((is_object($user) && $user instanceof $class) || (!is_object($user) && (is_subclass_of($user, $class) || $user == $class))) {
|
||||
$encoderKey = $class;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->encoders[$class];
|
||||
}
|
||||
|
||||
throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user));
|
||||
if (null === $encoderKey) {
|
||||
throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user));
|
||||
}
|
||||
|
||||
if (!$this->encoders[$encoderKey] instanceof PasswordEncoderInterface) {
|
||||
$this->encoders[$encoderKey] = $this->createEncoder($this->encoders[$encoderKey]);
|
||||
}
|
||||
|
||||
return $this->encoders[$encoderKey];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Core\Tests\Encoder;
|
||||
|
||||
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
@ -78,6 +79,59 @@ class EncoderFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
$expectedEncoder = new MessageDigestPasswordEncoder('sha1');
|
||||
$this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
|
||||
}
|
||||
|
||||
public function testGetNamedEncoderForEncoderAware()
|
||||
{
|
||||
$factory = new EncoderFactory(array(
|
||||
'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha256'),
|
||||
'encoder_name' => new MessageDigestPasswordEncoder('sha1')
|
||||
));
|
||||
|
||||
$encoder = $factory->getEncoder(new EncAwareUser('user', 'pass'));
|
||||
$expectedEncoder = new MessageDigestPasswordEncoder('sha1');
|
||||
$this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
|
||||
}
|
||||
|
||||
public function testGetNullNamedEncoderForEncoderAware()
|
||||
{
|
||||
$factory = new EncoderFactory(array(
|
||||
'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha1'),
|
||||
'encoder_name' => new MessageDigestPasswordEncoder('sha256')
|
||||
));
|
||||
|
||||
$user = new EncAwareUser('user', 'pass');
|
||||
$user->encoderName = null;
|
||||
$encoder = $factory->getEncoder($user);
|
||||
$expectedEncoder = new MessageDigestPasswordEncoder('sha1');
|
||||
$this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testGetInvalidNamedEncoderForEncoderAware()
|
||||
{
|
||||
$factory = new EncoderFactory(array(
|
||||
'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha1'),
|
||||
'encoder_name' => new MessageDigestPasswordEncoder('sha256')
|
||||
));
|
||||
|
||||
$user = new EncAwareUser('user', 'pass');
|
||||
$user->encoderName = 'invalid_encoder_name';
|
||||
$encoder = $factory->getEncoder($user);
|
||||
}
|
||||
|
||||
public function testGetEncoderForEncoderAwareWithClassName()
|
||||
{
|
||||
$factory = new EncoderFactory(array(
|
||||
'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha1'),
|
||||
'encoder_name' => new MessageDigestPasswordEncoder('sha256')
|
||||
));
|
||||
|
||||
$encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser');
|
||||
$expectedEncoder = new MessageDigestPasswordEncoder('sha1');
|
||||
$this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
|
||||
}
|
||||
}
|
||||
|
||||
class SomeUser implements UserInterface
|
||||
@ -92,3 +146,13 @@ class SomeUser implements UserInterface
|
||||
class SomeChildUser extends SomeUser
|
||||
{
|
||||
}
|
||||
|
||||
class EncAwareUser extends SomeUser implements EncoderAwareInterface
|
||||
{
|
||||
public $encoderName = 'encoder_name';
|
||||
|
||||
public function getEncoderName()
|
||||
{
|
||||
return $this->encoderName;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user