[Ldap] Fixed issue with Entry password attribute containing array of values and made password attribute configurable
This commit is contained in:
parent
4974a8b5f5
commit
dbf45e4a76
@ -35,6 +35,7 @@ class LdapFactory implements UserProviderFactoryInterface
|
|||||||
->replaceArgument(4, $config['default_roles'])
|
->replaceArgument(4, $config['default_roles'])
|
||||||
->replaceArgument(5, $config['uid_key'])
|
->replaceArgument(5, $config['uid_key'])
|
||||||
->replaceArgument(6, $config['filter'])
|
->replaceArgument(6, $config['filter'])
|
||||||
|
->replaceArgument(7, $config['password_attribute'])
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ class LdapFactory implements UserProviderFactoryInterface
|
|||||||
->end()
|
->end()
|
||||||
->scalarNode('uid_key')->defaultValue('sAMAccountName')->end()
|
->scalarNode('uid_key')->defaultValue('sAMAccountName')->end()
|
||||||
->scalarNode('filter')->defaultValue('({uid_key}={username})')->end()
|
->scalarNode('filter')->defaultValue('({uid_key}={username})')->end()
|
||||||
|
->scalarNode('password_attribute')->defaultNull()->end()
|
||||||
->end()
|
->end()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,10 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$provider->loadUserByUsername('foo');
|
$provider->loadUserByUsername('foo');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSuccessfulLoadUserByUsername()
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testLoadUserByUsernameFailsIfMoreThanOneLdapPasswordsInEntry()
|
||||||
{
|
{
|
||||||
$result = $this->getMock(CollectionInterface::class);
|
$result = $this->getMock(CollectionInterface::class);
|
||||||
$query = $this->getMock(QueryInterface::class);
|
$query = $this->getMock(QueryInterface::class);
|
||||||
@ -120,8 +123,95 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
|||||||
->method('offsetGet')
|
->method('offsetGet')
|
||||||
->with(0)
|
->with(0)
|
||||||
->will($this->returnValue(new Entry('foo', array(
|
->will($this->returnValue(new Entry('foo', array(
|
||||||
'sAMAccountName' => 'foo',
|
'sAMAccountName' => array('foo'),
|
||||||
'userpassword' => 'bar',
|
'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')
|
$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')
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\Security\Core\User;
|
namespace Symfony\Component\Security\Core\User;
|
||||||
|
|
||||||
use Symfony\Component\Ldap\Entry;
|
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\UnsupportedUserException;
|
||||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||||
@ -31,6 +32,7 @@ class LdapUserProvider implements UserProviderInterface
|
|||||||
private $searchPassword;
|
private $searchPassword;
|
||||||
private $defaultRoles;
|
private $defaultRoles;
|
||||||
private $defaultSearch;
|
private $defaultSearch;
|
||||||
|
private $passwordAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param LdapInterface $ldap
|
* @param LdapInterface $ldap
|
||||||
@ -41,7 +43,7 @@ class LdapUserProvider implements UserProviderInterface
|
|||||||
* @param string $uidKey
|
* @param string $uidKey
|
||||||
* @param string $filter
|
* @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->ldap = $ldap;
|
||||||
$this->baseDn = $baseDn;
|
$this->baseDn = $baseDn;
|
||||||
@ -49,6 +51,7 @@ class LdapUserProvider implements UserProviderInterface
|
|||||||
$this->searchPassword = $searchPassword;
|
$this->searchPassword = $searchPassword;
|
||||||
$this->defaultRoles = $defaultRoles;
|
$this->defaultRoles = $defaultRoles;
|
||||||
$this->defaultSearch = str_replace('{uid_key}', $uidKey, $filter);
|
$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';
|
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)
|
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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user