feature #11306 [DX] New service to simplify password encoding (aferrandini)

This PR was merged into the 2.6-dev branch.

Discussion
----------

[DX] New service to simplify password encoding

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #11299
| License       | MIT
| Doc PR | https://github.com/symfony/symfony-docs/pull/3995

This new service siplifies the way to encode a password. Just get the `security.password_encoder` service and encode the `User` password.

```php
$encoded = $this->container->get('security.password_encoder')
    ->encodePassword($user, $plainPassword);

$user->setPassword($encoded);
```

Commits
-------

7bc190a New service to simplify password encoding
This commit is contained in:
Fabien Potencier 2014-07-25 10:49:22 +02:00
commit eb48706ae4
4 changed files with 173 additions and 0 deletions

View File

@ -10,6 +10,7 @@
<parameter key="security.user_checker.class">Symfony\Component\Security\Core\User\UserChecker</parameter> <parameter key="security.user_checker.class">Symfony\Component\Security\Core\User\UserChecker</parameter>
<parameter key="security.encoder_factory.generic.class">Symfony\Component\Security\Core\Encoder\EncoderFactory</parameter> <parameter key="security.encoder_factory.generic.class">Symfony\Component\Security\Core\Encoder\EncoderFactory</parameter>
<parameter key="security.user_password_encoder.generic.class">Symfony\Component\Security\Core\Encoder\UserPasswordEncoder</parameter>
<parameter key="security.encoder.digest.class">Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder</parameter> <parameter key="security.encoder.digest.class">Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder</parameter>
<parameter key="security.encoder.plain.class">Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder</parameter> <parameter key="security.encoder.plain.class">Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder</parameter>
<parameter key="security.encoder.pbkdf2.class">Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder</parameter> <parameter key="security.encoder.pbkdf2.class">Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder</parameter>
@ -80,6 +81,12 @@
<service id="security.encoder_factory" alias="security.encoder_factory.generic"></service> <service id="security.encoder_factory" alias="security.encoder_factory.generic"></service>
<service id="security.user_password_encoder.generic" class="%security.user_password_encoder.generic.class%" public="false">
<argument type="service" id="security.encoder_factory"></argument>
</service>
<service id="security.password_encoder" alias="security.user_password_encoder.generic"></service>
<service id="security.user_checker" class="%security.user_checker.class%" public="false" /> <service id="security.user_checker" class="%security.user_checker.class%" public="false" />
<service id="security.expression_language" class="%security.expression_language.class%" public="false" /> <service id="security.expression_language" class="%security.expression_language.class%" public="false" />

View File

@ -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\Encoder;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* A generic password encoder
*
* @author Ariel Ferrandini <arielferrandini@gmail.com>
*/
class UserPasswordEncoder implements UserPasswordEncoderInterface
{
/**
* @var EncoderFactoryInterface
*/
private $encoderFactory;
/**
* @param EncoderFactoryInterface $encoderFactory The encoder factory
*/
public function __construct(EncoderFactoryInterface $encoderFactory)
{
$this->encoderFactory = $encoderFactory;
}
/**
* {@inheritdoc}
*/
public function encodePassword(UserInterface $user, $plainPassword)
{
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->encodePassword($plainPassword, $user->getSalt());
}
/**
* {@inheritdoc}
*/
public function isPasswordValid(UserInterface $user, $raw)
{
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->isPasswordValid($user->getPassword(), $raw, $user->getSalt());
}
}

View File

@ -0,0 +1,41 @@
<?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;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* UserPasswordEncoderInterface is the interface for the password encoder service.
*
* @author Ariel Ferrandini <arielferrandini@gmail.com>
*/
interface UserPasswordEncoderInterface
{
/**
*
* Encodes the plain password.
*
* @param UserInterface $user The user
* @param string $plainPassword The password to encode
*
* @return string The encoded password
*/
public function encodePassword(UserInterface $user, $plainPassword);
/**
* @param UserInterface $user The user
* @param string $raw A raw password
*
* @return bool true if the password is valid, false otherwise
*/
public function isPasswordValid(UserInterface $user, $raw);
}

View File

@ -0,0 +1,70 @@
<?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\Tests\Encoder;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
class UserPasswordEncoderTest extends \PHPUnit_Framework_TestCase
{
public function testEncodePassword()
{
$userMock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
$userMock->expects($this->any())
->method('getSalt')
->will($this->returnValue('userSalt'));
$mockEncoder = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');
$mockEncoder->expects($this->any())
->method('encodePassword')
->with($this->equalTo('plainPassword'), $this->equalTo('userSalt'))
->will($this->returnValue('encodedPassword'));
$mockEncoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
$mockEncoderFactory->expects($this->any())
->method('getEncoder')
->with($this->equalTo($userMock))
->will($this->returnValue($mockEncoder));
$passwordEncoder = new UserPasswordEncoder($mockEncoderFactory);
$encoded = $passwordEncoder->encodePassword($userMock, 'plainPassword');
$this->assertEquals('encodedPassword', $encoded);
}
public function testIsPasswordValid()
{
$userMock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
$userMock->expects($this->any())
->method('getSalt')
->will($this->returnValue('userSalt'));
$userMock->expects($this->any())
->method('getPassword')
->will($this->returnValue('encodedPassword'));
$mockEncoder = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');
$mockEncoder->expects($this->any())
->method('isPasswordValid')
->with($this->equalTo('encodedPassword'), $this->equalTo('plainPassword'), $this->equalTo('userSalt'))
->will($this->returnValue(true));
$mockEncoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
$mockEncoderFactory->expects($this->any())
->method('getEncoder')
->with($this->equalTo($userMock))
->will($this->returnValue($mockEncoder));
$passwordEncoder = new UserPasswordEncoder($mockEncoderFactory);
$isValid = $passwordEncoder->isPasswordValid($userMock, 'plainPassword');
$this->assertTrue($isValid);
}
}