Skip to content

Commit

Permalink
feature #11306 [DX] New service to simplify password encoding (aferra…
Browse files Browse the repository at this point in the history
…ndini)

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 | symfony/symfony-docs#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
  • Loading branch information
fabpot committed Jul 25, 2014
2 parents bf140a8 + 7bc190a commit eb48706
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 0 deletions.
Expand Up @@ -10,6 +10,7 @@
<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.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.plain.class">Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder</parameter>
<parameter key="security.encoder.pbkdf2.class">Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder</parameter>
Expand Down Expand Up @@ -80,6 +81,12 @@

<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.expression_language" class="%security.expression_language.class%" public="false" />
Expand Down
@@ -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());
}
}
@@ -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);
}
@@ -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);
}
}

0 comments on commit eb48706

Please sign in to comment.