summaryrefslogtreecommitdiffstats
path: root/Core
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2016-05-26 09:56:59 +0200
committerFabien Potencier <fabien.potencier@gmail.com>2016-05-26 09:56:59 +0200
commit421e01d2175d255f693d63fae3a53e704f963510 (patch)
tree639ab6790be94342984d73ab77b9dc7ee7ec6991 /Core
parented28bea5300aaf8388d11c9245afc21fa2a4861c (diff)
parent3b89f41a6a9e015da1bd008be13c985349f86e7b (diff)
downloadsymfony-security-421e01d2175d255f693d63fae3a53e704f963510.zip
symfony-security-421e01d2175d255f693d63fae3a53e704f963510.tar.gz
symfony-security-421e01d2175d255f693d63fae3a53e704f963510.tar.bz2
Merge branch '3.1'
* 3.1: [Console] SymfonyStyle: Align multi-line/very-long-line blocks [Console][DX] Fixed ambiguous error message when using a duplicate option shortcut Fix js comment in profiler [Ldap] Fixed issue with Entry password attribute containing array of values and made password attribute configurable [Serializer][#18837] adding a test [Cache] Drop counting hit/miss in ProxyAdapter [Serializer] AbstractObjectNormalizer: be sure that isAllowedAttribute is called [Serializer] ObjectNormalizer: add missing parameters
Diffstat (limited to 'Core')
-rw-r--r--Core/Tests/User/LdapUserProviderTest.php139
-rw-r--r--Core/User/LdapUserProvider.php41
2 files changed, 175 insertions, 5 deletions
diff --git a/Core/Tests/User/LdapUserProviderTest.php b/Core/Tests/User/LdapUserProviderTest.php
index 6876eec..b942e76 100644
--- a/Core/Tests/User/LdapUserProviderTest.php
+++ b/Core/Tests/User/LdapUserProviderTest.php
@@ -105,7 +105,10 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
$provider->loadUserByUsername('foo');
}
- public function testSuccessfulLoadUserByUsername()
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\InvalidArgumentException
+ */
+ public function testLoadUserByUsernameFailsIfMoreThanOneLdapPasswordsInEntry()
{
$result = $this->getMock(CollectionInterface::class);
$query = $this->getMock(QueryInterface::class);
@@ -120,8 +123,95 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
->method('offsetGet')
->with(0)
->will($this->returnValue(new Entry('foo', array(
- 'sAMAccountName' => 'foo',
- 'userpassword' => 'bar',
+ 'sAMAccountName' => array('foo'),
+ 'userpassword' => array('bar', 'baz'),
+ )
+ )))
+ ;
+ $result
+ ->expects($this->once())
+ ->method('count')
+ ->will($this->returnValue(1))
+ ;
+ $ldap
+ ->expects($this->once())
+ ->method('escape')
+ ->will($this->returnValue('foo'))
+ ;
+ $ldap
+ ->expects($this->once())
+ ->method('query')
+ ->will($this->returnValue($query))
+ ;
+
+ $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, array(), 'sAMAccountName', '({uid_key}={username})', 'userpassword');
+ $this->assertInstanceOf(
+ 'Symfony\Component\Security\Core\User\User',
+ $provider->loadUserByUsername('foo')
+ );
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\InvalidArgumentException
+ */
+ public function testLoadUserByUsernameFailsIfEntryHasNoPasswordAttribute()
+ {
+ $result = $this->getMock(CollectionInterface::class);
+ $query = $this->getMock(QueryInterface::class);
+ $query
+ ->expects($this->once())
+ ->method('execute')
+ ->will($this->returnValue($result))
+ ;
+ $ldap = $this->getMock(LdapInterface::class);
+ $result
+ ->expects($this->once())
+ ->method('offsetGet')
+ ->with(0)
+ ->will($this->returnValue(new Entry('foo', array(
+ 'sAMAccountName' => array('foo'),
+ )
+ )))
+ ;
+ $result
+ ->expects($this->once())
+ ->method('count')
+ ->will($this->returnValue(1))
+ ;
+ $ldap
+ ->expects($this->once())
+ ->method('escape')
+ ->will($this->returnValue('foo'))
+ ;
+ $ldap
+ ->expects($this->once())
+ ->method('query')
+ ->will($this->returnValue($query))
+ ;
+
+ $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, array(), 'sAMAccountName', '({uid_key}={username})', 'userpassword');
+ $this->assertInstanceOf(
+ 'Symfony\Component\Security\Core\User\User',
+ $provider->loadUserByUsername('foo')
+ );
+ }
+
+ public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttribute()
+ {
+ $result = $this->getMock(CollectionInterface::class);
+ $query = $this->getMock(QueryInterface::class);
+ $query
+ ->expects($this->once())
+ ->method('execute')
+ ->will($this->returnValue($result))
+ ;
+ $ldap = $this->getMock(LdapInterface::class);
+ $result
+ ->expects($this->once())
+ ->method('offsetGet')
+ ->with(0)
+ ->will($this->returnValue(new Entry('foo', array(
+ 'sAMAccountName' => array('foo'),
)
)))
;
@@ -147,4 +237,47 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
$provider->loadUserByUsername('foo')
);
}
+
+ public function testLoadUserByUsernameIsSuccessfulWithPasswordAttribute()
+ {
+ $result = $this->getMock(CollectionInterface::class);
+ $query = $this->getMock(QueryInterface::class);
+ $query
+ ->expects($this->once())
+ ->method('execute')
+ ->will($this->returnValue($result))
+ ;
+ $ldap = $this->getMock(LdapInterface::class);
+ $result
+ ->expects($this->once())
+ ->method('offsetGet')
+ ->with(0)
+ ->will($this->returnValue(new Entry('foo', array(
+ 'sAMAccountName' => array('foo'),
+ 'userpassword' => array('bar'),
+ )
+ )))
+ ;
+ $result
+ ->expects($this->once())
+ ->method('count')
+ ->will($this->returnValue(1))
+ ;
+ $ldap
+ ->expects($this->once())
+ ->method('escape')
+ ->will($this->returnValue('foo'))
+ ;
+ $ldap
+ ->expects($this->once())
+ ->method('query')
+ ->will($this->returnValue($query))
+ ;
+
+ $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, array(), 'sAMAccountName', '({uid_key}={username})', 'userpassword');
+ $this->assertInstanceOf(
+ 'Symfony\Component\Security\Core\User\User',
+ $provider->loadUserByUsername('foo')
+ );
+ }
}
diff --git a/Core/User/LdapUserProvider.php b/Core/User/LdapUserProvider.php
index a37981c..e722c98 100644
--- a/Core/User/LdapUserProvider.php
+++ b/Core/User/LdapUserProvider.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Core\User;
use Symfony\Component\Ldap\Entry;
+use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Ldap\Exception\ConnectionException;
@@ -31,6 +32,7 @@ class LdapUserProvider implements UserProviderInterface
private $searchPassword;
private $defaultRoles;
private $defaultSearch;
+ private $passwordAttribute;
/**
* @param LdapInterface $ldap
@@ -41,7 +43,7 @@ class LdapUserProvider implements UserProviderInterface
* @param string $uidKey
* @param string $filter
*/
- public function __construct(LdapInterface $ldap, $baseDn, $searchDn = null, $searchPassword = null, array $defaultRoles = array(), $uidKey = 'sAMAccountName', $filter = '({uid_key}={username})')
+ public function __construct(LdapInterface $ldap, $baseDn, $searchDn = null, $searchPassword = null, array $defaultRoles = array(), $uidKey = 'sAMAccountName', $filter = '({uid_key}={username})', $passwordAttribute = null)
{
$this->ldap = $ldap;
$this->baseDn = $baseDn;
@@ -49,6 +51,7 @@ class LdapUserProvider implements UserProviderInterface
$this->searchPassword = $searchPassword;
$this->defaultRoles = $defaultRoles;
$this->defaultSearch = str_replace('{uid_key}', $uidKey, $filter);
+ $this->passwordAttribute = $passwordAttribute;
}
/**
@@ -99,8 +102,42 @@ class LdapUserProvider implements UserProviderInterface
return $class === 'Symfony\Component\Security\Core\User\User';
}
+ /**
+ * Loads a user from an LDAP entry.
+ *
+ * @param string $username
+ * @param Entry $entry
+ *
+ * @return User
+ */
private function loadUser($username, Entry $entry)
{
- return new User($username, $entry->getAttribute('userpassword'), $this->defaultRoles);
+ $password = $this->getPassword($entry);
+
+ return new User($username, $password, $this->defaultRoles);
+ }
+
+ /**
+ * Fetches the password from an LDAP entry.
+ *
+ * @param null|Entry $entry
+ */
+ private function getPassword(Entry $entry)
+ {
+ if (null === $this->passwordAttribute) {
+ return;
+ }
+
+ if (!$entry->hasAttribute($this->passwordAttribute)) {
+ throw new InvalidArgumentException(sprintf('Missing attribute "%s" for user "%s".', $this->passwordAttribute, $entry->getDn()));
+ }
+
+ $values = $entry->getAttribute($this->passwordAttribute);
+
+ if (1 !== count($values)) {
+ throw new InvalidArgumentException(sprintf('Attribute "%s" has multiple values.', $this->passwordAttribute));
+ }
+
+ return $values[0];
}
}