Commit 7f13e76f authored by Nikolay Labinskiy's avatar Nikolay Labinskiy

use bcrypt by default as encoder #1312; add pbkdf2 encoder

parent 800912d3
...@@ -10,6 +10,8 @@ Parameters ...@@ -10,6 +10,8 @@ Parameters
* **security.hide_user_not_found** (optional): Defines whether to hide user not * **security.hide_user_not_found** (optional): Defines whether to hide user not
found exception or not. Defaults to ``true``. found exception or not. Defaults to ``true``.
* **security.encoder.bcrypt.cost** (optional): Defines BCrypt password encoder cost. Defaults to 13.
Services Services
-------- --------
...@@ -36,9 +38,15 @@ Services ...@@ -36,9 +38,15 @@ Services
Request object. Request object.
* **security.encoder_factory**: Defines the encoding strategies for user * **security.encoder_factory**: Defines the encoding strategies for user
passwords (default to use a digest algorithm for all users). passwords (uses ``security.default_encoder``).
* **security.default_encoder**: The encoder to use by default for all users (BCrypt).
* **security.encoder.digest**: Digest password encoder.
* **security.encoder.bcrypt**: BCrypt password encoder.
* **security.encoder.digest**: The encoder to use by default for all users. * **security.encoder.pbkdf2**: Pbkdf2 password encoder.
* **user**: Returns the current user * **user**: Returns the current user
...@@ -552,20 +560,36 @@ sample users:: ...@@ -552,20 +560,36 @@ sample users::
Defining a custom Encoder Defining a custom Encoder
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
By default, Silex uses the ``sha512`` algorithm to encode passwords. By default, Silex uses the ``BCrypt`` algorithm to encode passwords.
Additionally, the password is encoded multiple times and converted to base64. Additionally, the password is encoded multiple times.
You can change these defaults by overriding the ``security.encoder.digest`` You can change these defaults by overriding ``security.default_encoder``
service:: service to return one of the predefined encoders:
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; * **security.encoder.digest**: Digest password encoder.
* **security.encoder.bcrypt**: BCrypt password encoder.
* **security.encoder.pbkdf2**: Pbkdf2 password encoder.
.. code-block:: php
$app['security.encoder.digest'] = function ($app) { $app['security.default_encoder'] = function ($app) {
// use the sha1 algorithm return $app['security.encoder.pbkdf2'];
// don't base64 encode the password
// use only 1 iteration
return new MessageDigestPasswordEncoder('sha1', false, 1);
}; };
Or you can define you own, fully customizable encoder::
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
$app['security.default_encoder'] = function ($app) {
// Plain text (e.g. for debugging)
return new PlaintextPasswordEncoder();
};
.. tip::
You can change the default BCrypt encoding cost by overriding ``security.encoder.bcrypt.cost``
Defining a custom Authentication Provider Defining a custom Authentication Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
...@@ -26,6 +26,8 @@ use Symfony\Component\Security\Core\User\UserChecker; ...@@ -26,6 +26,8 @@ use Symfony\Component\Security\Core\User\UserChecker;
use Symfony\Component\Security\Core\User\InMemoryUserProvider; use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\Encoder\EncoderFactory; use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;
use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider; use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider; use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager; use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
...@@ -78,6 +80,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -78,6 +80,7 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
$app['security.role_hierarchy'] = array(); $app['security.role_hierarchy'] = array();
$app['security.access_rules'] = array(); $app['security.access_rules'] = array();
$app['security.hide_user_not_found'] = true; $app['security.hide_user_not_found'] = true;
$app['security.encoder.bcrypt.cost'] = 13;
$app['security.authorization_checker'] = function ($app) { $app['security.authorization_checker'] = function ($app) {
return new AuthorizationChecker($app['security.token_storage'], $app['security.authentication_manager'], $app['security.access_manager']); return new AuthorizationChecker($app['security.token_storage'], $app['security.authentication_manager'], $app['security.access_manager']);
...@@ -109,14 +112,27 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener ...@@ -109,14 +112,27 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener
// by default, all users use the digest encoder // by default, all users use the digest encoder
$app['security.encoder_factory'] = function ($app) { $app['security.encoder_factory'] = function ($app) {
return new EncoderFactory(array( return new EncoderFactory(array(
'Symfony\Component\Security\Core\User\UserInterface' => $app['security.encoder.digest'], 'Symfony\Component\Security\Core\User\UserInterface' => $app['security.default_encoder'],
)); ));
}; };
// by default, all users use the BCrypt encoder
$app['security.default_encoder'] = function ($app) {
return $app['security.encoder.bcrypt'];
};
$app['security.encoder.digest'] = function ($app) { $app['security.encoder.digest'] = function ($app) {
return new MessageDigestPasswordEncoder(); return new MessageDigestPasswordEncoder();
}; };
$app['security.encoder.bcrypt'] = function ($app) {
return new BCryptPasswordEncoder($app['security.encoder.bcrypt.cost']);
};
$app['security.encoder.pbkdf2'] = function ($app) {
return new Pbkdf2PasswordEncoder();
};
$app['security.user_checker'] = function ($app) { $app['security.user_checker'] = function ($app) {
return new UserChecker(); return new UserChecker();
}; };
......
...@@ -25,11 +25,16 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase ...@@ -25,11 +25,16 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
public function testEncodePassword() public function testEncodePassword()
{ {
$app = $this->createApplication(array( $app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
)); ));
$user = new User('foo', 'bar'); $user = new User('foo', 'bar');
$this->assertEquals('5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg==', $app->encodePassword($user, 'foo')); $password = 'foo';
$encoded = $app->encodePassword($user, $password);
$this->assertTrue(
$app['security.encoder_factory']->getEncoder($user)->isPasswordValid($encoded, $password, $user->getSalt())
);
} }
/** /**
...@@ -48,8 +53,8 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase ...@@ -48,8 +53,8 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
$request = Request::create('/'); $request = Request::create('/');
$app = $this->createApplication(array( $app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
'monique' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'monique' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
)); ));
$app->get('/', function () { return 'foo'; }); $app->get('/', function () { return 'foo'; });
......
...@@ -77,7 +77,7 @@ class RememberMeServiceProviderTest extends WebTestCase ...@@ -77,7 +77,7 @@ class RememberMeServiceProviderTest extends WebTestCase
'remember_me' => array(), 'remember_me' => array(),
'logout' => true, 'logout' => true,
'users' => array( 'users' => array(
'fabien' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'fabien' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
), ),
), ),
); );
......
...@@ -187,7 +187,7 @@ class SecurityServiceProviderTest extends WebTestCase ...@@ -187,7 +187,7 @@ class SecurityServiceProviderTest extends WebTestCase
'default' => array( 'default' => array(
'http' => true, 'http' => true,
'users' => array( 'users' => array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
), ),
), ),
), ),
...@@ -271,8 +271,8 @@ class SecurityServiceProviderTest extends WebTestCase ...@@ -271,8 +271,8 @@ class SecurityServiceProviderTest extends WebTestCase
'logout' => true, 'logout' => true,
'users' => array( 'users' => array(
// password is foo // password is foo
'fabien' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'fabien' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'admin' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
), ),
), ),
), ),
...@@ -322,8 +322,8 @@ class SecurityServiceProviderTest extends WebTestCase ...@@ -322,8 +322,8 @@ class SecurityServiceProviderTest extends WebTestCase
'http' => true, 'http' => true,
'users' => array( 'users' => array(
// password is foo // password is foo
'dennis' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'dennis' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'admin' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
), ),
), ),
), ),
......
...@@ -74,7 +74,7 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase ...@@ -74,7 +74,7 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
'default' => array( 'default' => array(
'http' => true, 'http' => true,
'users' => array( 'users' => array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='), 'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
), ),
), ),
), ),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment