feature #17560 [Ldap] Improving the LDAP component (csarrazi)
This PR was merged into the 3.1-dev branch. Discussion ---------- [Ldap] Improving the LDAP component | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | yes | Deprecations? | no | Tests pass? | no | Fixed tickets | #14602 | License | MIT | Doc PR | not yet This PR will address a few issues mentioned in #14602. * [x] Integrate the Config component in order to simplify the client's configuration * [x] Separate Connection handling from the Client * [x] Support for multiple drivers * [x] Add functional tests * [x] Update Security component Commits -------34d3c85
Added compatibility layer for previous version of the Security component81cb79b
Improved the Ldap Component
This commit is contained in:
commit
7848a463b2
@ -6,6 +6,8 @@ addons:
|
||||
apt_packages:
|
||||
- parallel
|
||||
- language-pack-fr-base
|
||||
- ldap-utils
|
||||
- slapd
|
||||
|
||||
env:
|
||||
global:
|
||||
@ -48,6 +50,11 @@ before_install:
|
||||
- if [[ $deps != skip ]]; then composer self-update; fi;
|
||||
- if [[ $deps != skip ]]; then ./phpunit install; fi;
|
||||
- export PHPUNIT=$(readlink -f ./phpunit)
|
||||
- mkdir /tmp/slapd
|
||||
- slapd -f src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf -h ldap://localhost:3389 &
|
||||
- sleep 3
|
||||
- ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/base.ldif
|
||||
- ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif
|
||||
|
||||
install:
|
||||
- if [[ $deps != skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi;
|
||||
|
@ -43,7 +43,6 @@ install:
|
||||
- IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_pdo_sqlite.dll >> php.ini-max
|
||||
- IF %PHP%==1 echo extension=php_ldap.dll >> php.ini-max
|
||||
- appveyor DownloadFile https://getcomposer.org/composer.phar
|
||||
- copy /Y php.ini-max php.ini
|
||||
- cd c:\projects\symfony
|
||||
|
45
src/Symfony/Component/Ldap/Adapter/AbstractConnection.php
Normal file
45
src/Symfony/Component/Ldap/Adapter/AbstractConnection.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?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\Ldap\Adapter;
|
||||
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
abstract class AbstractConnection implements ConnectionInterface
|
||||
{
|
||||
protected $config;
|
||||
|
||||
public function __construct(array $config = array())
|
||||
{
|
||||
$resolver = new OptionsResolver();
|
||||
$resolver->setDefaults(array(
|
||||
'host' => null,
|
||||
'port' => 389,
|
||||
'version' => 3,
|
||||
'useSsl' => false,
|
||||
'useStartTls' => false,
|
||||
'optReferrals' => false,
|
||||
));
|
||||
$resolver->setNormalizer('host', function (Options $options, $value) {
|
||||
if ($value && $options['useSsl']) {
|
||||
return 'ldaps://'.$value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
});
|
||||
|
||||
$this->config = $resolver->resolve($config);
|
||||
}
|
||||
}
|
48
src/Symfony/Component/Ldap/Adapter/AbstractQuery.php
Normal file
48
src/Symfony/Component/Ldap/Adapter/AbstractQuery.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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\Ldap\Adapter;
|
||||
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
abstract class AbstractQuery implements QueryInterface
|
||||
{
|
||||
protected $connection;
|
||||
protected $dn;
|
||||
protected $query;
|
||||
protected $options;
|
||||
|
||||
public function __construct(ConnectionInterface $connection, $dn, $query, array $options = array())
|
||||
{
|
||||
$resolver = new OptionsResolver();
|
||||
$resolver->setDefaults(array(
|
||||
'filter' => '*',
|
||||
'maxItems' => 0,
|
||||
'sizeLimit' => 0,
|
||||
'timeout' => 0,
|
||||
'deref' => static::DEREF_NEVER,
|
||||
'attrsOnly' => 0,
|
||||
));
|
||||
$resolver->setAllowedValues('deref', array(static::DEREF_ALWAYS, static::DEREF_NEVER, static::DEREF_FINDING, static::DEREF_SEARCHING));
|
||||
$resolver->setNormalizer('filter', function (Options $options, $value) {
|
||||
return is_array($value) ? $value : array($value);
|
||||
});
|
||||
|
||||
$this->connection = $connection;
|
||||
$this->dn = $dn;
|
||||
$this->query = $query;
|
||||
$this->options = $resolver->resolve($options);
|
||||
}
|
||||
}
|
47
src/Symfony/Component/Ldap/Adapter/AdapterInterface.php
Normal file
47
src/Symfony/Component/Ldap/Adapter/AdapterInterface.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?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\Ldap\Adapter;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
interface AdapterInterface
|
||||
{
|
||||
/**
|
||||
* Returns the current connection.
|
||||
*
|
||||
* @return ConnectionInterface
|
||||
*/
|
||||
public function getConnection();
|
||||
|
||||
/**
|
||||
* Creates a new Query.
|
||||
*
|
||||
* @param $dn
|
||||
* @param $query
|
||||
* @param array $options
|
||||
*
|
||||
* @return QueryInterface
|
||||
*/
|
||||
public function createQuery($dn, $query, array $options = array());
|
||||
|
||||
/**
|
||||
* Escape a string for use in an LDAP filter or DN.
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape($subject, $ignore = '', $flags = 0);
|
||||
}
|
25
src/Symfony/Component/Ldap/Adapter/CollectionInterface.php
Normal file
25
src/Symfony/Component/Ldap/Adapter/CollectionInterface.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?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\Ldap\Adapter;
|
||||
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
interface CollectionInterface extends \Countable, \IteratorAggregate, \ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @return Entry[]
|
||||
*/
|
||||
public function toArray();
|
||||
}
|
33
src/Symfony/Component/Ldap/Adapter/ConnectionInterface.php
Normal file
33
src/Symfony/Component/Ldap/Adapter/ConnectionInterface.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?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\Ldap\Adapter;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
interface ConnectionInterface
|
||||
{
|
||||
/**
|
||||
* Checks whether the connection was already bound or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBound();
|
||||
|
||||
/**
|
||||
* Binds the connection against a DN and password.
|
||||
*
|
||||
* @param string $dn The user's DN
|
||||
* @param string $password The associated password
|
||||
*/
|
||||
public function bind($dn = null, $password = null);
|
||||
}
|
74
src/Symfony/Component/Ldap/Adapter/ExtLdap/Adapter.php
Normal file
74
src/Symfony/Component/Ldap/Adapter/ExtLdap/Adapter.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?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\Ldap\Adapter\ExtLdap;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\AdapterInterface;
|
||||
use Symfony\Component\Ldap\Exception\LdapException;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class Adapter implements AdapterInterface
|
||||
{
|
||||
private $config;
|
||||
private $connection;
|
||||
|
||||
public function __construct(array $config = array())
|
||||
{
|
||||
if (!extension_loaded('ldap')) {
|
||||
throw new LdapException('The LDAP PHP extension is not enabled.');
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
if (null === $this->connection) {
|
||||
$this->connection = new Connection($this->config);
|
||||
}
|
||||
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createQuery($dn, $query, array $options = array())
|
||||
{
|
||||
return new Query($this->getConnection(), $dn, $query, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function escape($subject, $ignore = '', $flags = 0)
|
||||
{
|
||||
$value = ldap_escape($subject, $ignore, $flags);
|
||||
|
||||
// Per RFC 4514, leading/trailing spaces should be encoded in DNs, as well as carriage returns.
|
||||
if ((int) $flags & LDAP_ESCAPE_DN) {
|
||||
if (!empty($value) && $value[0] === ' ') {
|
||||
$value = '\\20'.substr($value, 1);
|
||||
}
|
||||
if (!empty($value) && $value[strlen($value) - 1] === ' ') {
|
||||
$value = substr($value, 0, -1).'\\20';
|
||||
}
|
||||
$value = str_replace("\r", '\0d', $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
108
src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php
Normal file
108
src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?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\Ldap\Adapter\ExtLdap;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\CollectionInterface;
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class Collection implements CollectionInterface
|
||||
{
|
||||
private $connection;
|
||||
private $search;
|
||||
private $entries;
|
||||
|
||||
public function __construct(Connection $connection, Query $search, array $entries = array())
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->search = $search;
|
||||
$this->entries = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return count($this->entries);
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new ResultIterator($this->connection, $this->search);
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
return isset($this->entries[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->entries[$offset]) ? $this->entries[$offset] : null;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
$this->entries[$offset] = $value;
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
unset($this->entries[$offset]);
|
||||
}
|
||||
|
||||
private function initialize()
|
||||
{
|
||||
if (null === $this->entries) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($this->connection->getResource(), $this->search->getResource());
|
||||
|
||||
if (0 === $entries['count']) {
|
||||
return array();
|
||||
}
|
||||
|
||||
unset($entries['count']);
|
||||
|
||||
$this->entries = array_map(function (array $entry) {
|
||||
$dn = $entry['dn'];
|
||||
$attributes = array_diff_key($entry, array_flip(range(0, $entry['count'] - 1)) + array(
|
||||
'count' => null,
|
||||
'dn' => null,
|
||||
));
|
||||
array_walk($attributes, function (&$value) {
|
||||
unset($value['count']);
|
||||
});
|
||||
|
||||
return new Entry($dn, $attributes);
|
||||
}, $entries);
|
||||
}
|
||||
}
|
89
src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php
Normal file
89
src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?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\Ldap\Adapter\ExtLdap;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\AbstractConnection;
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class Connection extends AbstractConnection
|
||||
{
|
||||
/** @var bool */
|
||||
private $bound = false;
|
||||
|
||||
/** @var resource */
|
||||
private $connection;
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
public function isBound()
|
||||
{
|
||||
return $this->bound;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bind($dn = null, $password = null)
|
||||
{
|
||||
if (!$this->connection) {
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
if (false === @ldap_bind($this->connection, $dn, $password)) {
|
||||
throw new ConnectionException(ldap_error($this->connection));
|
||||
}
|
||||
|
||||
$this->bound = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a link resource.
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
private function connect()
|
||||
{
|
||||
if ($this->connection) {
|
||||
return;
|
||||
}
|
||||
$host = $this->config['host'];
|
||||
|
||||
ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this->config['version']);
|
||||
ldap_set_option($this->connection, LDAP_OPT_REFERRALS, $this->config['optReferrals']);
|
||||
|
||||
$this->connection = ldap_connect($host, $this->config['port']);
|
||||
|
||||
if ($this->config['useStartTls']) {
|
||||
ldap_start_tls($this->connection);
|
||||
}
|
||||
}
|
||||
|
||||
private function disconnect()
|
||||
{
|
||||
if ($this->connection && is_resource($this->connection)) {
|
||||
ldap_close($this->connection);
|
||||
}
|
||||
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
72
src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php
Normal file
72
src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?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\Ldap\Adapter\ExtLdap;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\AbstractQuery;
|
||||
use Symfony\Component\Ldap\Exception\LdapException;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class Query extends AbstractQuery
|
||||
{
|
||||
/** @var Connection */
|
||||
protected $connection;
|
||||
|
||||
/** @var resource */
|
||||
private $search;
|
||||
|
||||
public function __construct(Connection $connection, $dn, $query, array $options = array())
|
||||
{
|
||||
parent::__construct($connection, $dn, $query, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
// If the connection is not bound, then we try an anonymous bind.
|
||||
if (!$this->connection->isBound()) {
|
||||
$this->connection->bind();
|
||||
}
|
||||
|
||||
$con = $this->connection->getResource();
|
||||
|
||||
$this->search = ldap_search(
|
||||
$con,
|
||||
$this->dn,
|
||||
$this->query,
|
||||
$this->options['filter'],
|
||||
$this->options['attrsOnly'],
|
||||
$this->options['maxItems'],
|
||||
$this->options['timeout'],
|
||||
$this->options['deref']
|
||||
);
|
||||
|
||||
if (!$this->search) {
|
||||
throw new LdapException(sprintf('Could not complete search with dn "%s", query "%s" and filters "%s"', $this->dn, $this->query, implode(',', $this->options['filter'])));
|
||||
};
|
||||
|
||||
return new Collection($this->connection, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a LDAP search resource.
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->search;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?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\Ldap\Adapter\ExtLdap;
|
||||
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class ResultIterator implements \Iterator
|
||||
{
|
||||
private $connection;
|
||||
private $search;
|
||||
private $current;
|
||||
private $key;
|
||||
|
||||
public function __construct(Connection $connection, Query $search)
|
||||
{
|
||||
$this->connection = $connection->getResource();
|
||||
$this->search = $search->getResource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the current entry.
|
||||
*
|
||||
* @return Entry
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
$attributes = ldap_get_attributes($this->connection, $this->current);
|
||||
$dn = ldap_get_dn($this->connection, $this->current);
|
||||
|
||||
return new Entry($dn, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cursor to the next entry.
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$this->current = ldap_next_entry($this->connection, $this->current);
|
||||
++$this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current key.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the current entry is valid or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return false !== $this->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewinds the iterator to the first entry.
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->current = ldap_first_entry($this->connection, $this->search);
|
||||
}
|
||||
}
|
35
src/Symfony/Component/Ldap/Adapter/QueryInterface.php
Normal file
35
src/Symfony/Component/Ldap/Adapter/QueryInterface.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
namespace Symfony\Component\Ldap\Adapter;
|
||||
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
interface QueryInterface
|
||||
{
|
||||
const DEREF_NEVER = 0;
|
||||
const DEREF_SEARCHING = 1;
|
||||
const DEREF_FINDING = 2;
|
||||
const DEREF_ALWAYS = 3;
|
||||
|
||||
/**
|
||||
* Executes a query and returns the list of Ldap entries.
|
||||
*
|
||||
* @return CollectionInterface|Entry[]
|
||||
*/
|
||||
public function execute();
|
||||
}
|
48
src/Symfony/Component/Ldap/BaseLdapInterface.php
Normal file
48
src/Symfony/Component/Ldap/BaseLdapInterface.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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\Ldap;
|
||||
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
|
||||
/**
|
||||
* Base Ldap interface.
|
||||
*
|
||||
* This interface is here for reusability in the BC layer,
|
||||
* and will be merged in LdapInterface in Symfony 4.0.
|
||||
*
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface BaseLdapInterface
|
||||
{
|
||||
/**
|
||||
* Return a connection bound to the ldap.
|
||||
*
|
||||
* @param string $dn A LDAP dn
|
||||
* @param string $password A password
|
||||
*
|
||||
* @throws ConnectionException If dn / password could not be bound.
|
||||
*/
|
||||
public function bind($dn = null, $password = null);
|
||||
|
||||
/**
|
||||
* Escape a string for use in an LDAP filter or DN.
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape($subject, $ignore = '', $flags = 0);
|
||||
}
|
62
src/Symfony/Component/Ldap/Entry.php
Normal file
62
src/Symfony/Component/Ldap/Entry.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?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\Ldap;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class Entry
|
||||
{
|
||||
private $dn;
|
||||
private $attributes;
|
||||
|
||||
public function __construct($dn, array $attributes = array())
|
||||
{
|
||||
$this->dn = $dn;
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entry's DN.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDn()
|
||||
{
|
||||
return $this->dn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specific attribute's value.
|
||||
*
|
||||
* As LDAP can return multiple values for a single attribute,
|
||||
* this value is returned as an array.
|
||||
*
|
||||
* @param $name string The name of the attribute
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complete list of attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
}
|
@ -15,9 +15,7 @@ namespace Symfony\Component\Ldap\Exception;
|
||||
* ConnectionException is throw if binding to ldap can not be established.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ConnectionException extends \RuntimeException
|
||||
class ConnectionException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
<?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\Ldap\Exception;
|
||||
|
||||
/**
|
||||
* LdapException is throw if php ldap module is not loaded.
|
||||
*
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class DriverNotFoundException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
21
src/Symfony/Component/Ldap/Exception/ExceptionInterface.php
Normal file
21
src/Symfony/Component/Ldap/Exception/ExceptionInterface.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?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\Ldap\Exception;
|
||||
|
||||
/**
|
||||
* Base ExceptionInterface for the Ldap component.
|
||||
*
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
@ -15,9 +15,7 @@ namespace Symfony\Component\Ldap\Exception;
|
||||
* LdapException is throw if php ldap module is not loaded.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class LdapException extends \RuntimeException
|
||||
class LdapException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
79
src/Symfony/Component/Ldap/Ldap.php
Normal file
79
src/Symfony/Component/Ldap/Ldap.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?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\Ldap;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\AdapterInterface;
|
||||
use Symfony\Component\Ldap\Exception\DriverNotFoundException;
|
||||
|
||||
/**
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
final class Ldap implements LdapInterface
|
||||
{
|
||||
private $adapter;
|
||||
|
||||
private static $adapterMap = array(
|
||||
'ext_ldap' => 'Symfony\Component\Ldap\Adapter\ExtLdap\Adapter',
|
||||
);
|
||||
|
||||
public function __construct(AdapterInterface $adapter)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bind($dn = null, $password = null)
|
||||
{
|
||||
$this->adapter->getConnection()->bind($dn, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query($dn, $query, array $options = array())
|
||||
{
|
||||
return $this->adapter->createQuery($dn, $query, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function escape($subject, $ignore = '', $flags = 0)
|
||||
{
|
||||
return $this->adapter->escape($subject, $ignore, $flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Ldap instance.
|
||||
*
|
||||
* @param string $adapter The adapter name
|
||||
* @param array $config The adapter's configuration
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function create($adapter, array $config = array())
|
||||
{
|
||||
if (!isset(self::$adapterMap[$adapter])) {
|
||||
throw new DriverNotFoundException(sprintf(
|
||||
'Adapter "%s" not found. You should use one of: %s',
|
||||
$adapter,
|
||||
implode(', ', self::$adapterMap)
|
||||
));
|
||||
}
|
||||
|
||||
$class = self::$adapterMap[$adapter];
|
||||
|
||||
return new self(new $class($config));
|
||||
}
|
||||
}
|
@ -11,53 +11,29 @@
|
||||
|
||||
namespace Symfony\Component\Ldap;
|
||||
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
use Symfony\Component\Ldap\Exception\LdapException;
|
||||
|
||||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*
|
||||
* @internal
|
||||
* @deprecated The LdapClient class will be removed in Symfony 4.0. You should use the Ldap class instead.
|
||||
*/
|
||||
class LdapClient implements LdapClientInterface
|
||||
final class LdapClient implements LdapClientInterface
|
||||
{
|
||||
private $host;
|
||||
private $port;
|
||||
private $version;
|
||||
private $useSsl;
|
||||
private $useStartTls;
|
||||
private $optReferrals;
|
||||
private $connection;
|
||||
private $ldap;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param int $version
|
||||
* @param bool $useSsl
|
||||
* @param bool $useStartTls
|
||||
* @param bool $optReferrals
|
||||
*/
|
||||
public function __construct($host = null, $port = 389, $version = 3, $useSsl = false, $useStartTls = false, $optReferrals = false)
|
||||
public function __construct($host = null, $port = 389, $version = 3, $useSsl = false, $useStartTls = false, $optReferrals = false, LdapInterface $ldap = null)
|
||||
{
|
||||
if (!extension_loaded('ldap')) {
|
||||
throw new LdapException('The ldap module is needed.');
|
||||
}
|
||||
$config = array(
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'version' => $version,
|
||||
'useSsl' => (bool) $useSsl,
|
||||
'useStartTls' => (bool) $useStartTls,
|
||||
'optReferrals' => (bool) $optReferrals,
|
||||
);
|
||||
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->version = $version;
|
||||
$this->useSsl = (bool) $useSsl;
|
||||
$this->useStartTls = (bool) $useStartTls;
|
||||
$this->optReferrals = (bool) $optReferrals;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->disconnect();
|
||||
$this->ldap = null !== $ldap ? $ldap : Ldap::create('ext_ldap', $config);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,13 +41,7 @@ class LdapClient implements LdapClientInterface
|
||||
*/
|
||||
public function bind($dn = null, $password = null)
|
||||
{
|
||||
if (!$this->connection) {
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
if (false === @ldap_bind($this->connection, $dn, $password)) {
|
||||
throw new ConnectionException(ldap_error($this->connection));
|
||||
}
|
||||
$this->ldap->bind($dn, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,18 +49,30 @@ class LdapClient implements LdapClientInterface
|
||||
*/
|
||||
public function find($dn, $query, $filter = '*')
|
||||
{
|
||||
if (!is_array($filter)) {
|
||||
$filter = array($filter);
|
||||
@trigger_error('The "find" method is deprecated since version 3.1 and will be removed in 4.0. Use the "query" method instead.', E_USER_DEPRECATED);
|
||||
|
||||
$query = $this->ldap->query($dn, $query, array('filter' => $filter));
|
||||
$entries = $query->execute();
|
||||
$result = array();
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$resultEntry = array();
|
||||
|
||||
foreach ($entry->getAttributes() as $attribute => $values) {
|
||||
$resultAttribute = $values;
|
||||
|
||||
$resultAttribute['count'] = count($values);
|
||||
$resultEntry[] = $resultAttribute;
|
||||
$resultEntry[$attribute] = $resultAttribute;
|
||||
}
|
||||
|
||||
$resultEntry['count'] = count($resultEntry) / 2;
|
||||
$result[] = $resultEntry;
|
||||
}
|
||||
|
||||
$search = ldap_search($this->connection, $dn, $query, $filter);
|
||||
$infos = ldap_get_entries($this->connection, $search);
|
||||
$result['count'] = count($result);
|
||||
|
||||
if (0 === $infos['count']) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $infos;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,48 +80,6 @@ class LdapClient implements LdapClientInterface
|
||||
*/
|
||||
public function escape($subject, $ignore = '', $flags = 0)
|
||||
{
|
||||
$value = ldap_escape($subject, $ignore, $flags);
|
||||
|
||||
// Per RFC 4514, leading/trailing spaces should be encoded in DNs, as well as carriage returns.
|
||||
if ((int) $flags & LDAP_ESCAPE_DN) {
|
||||
if (!empty($value) && $value[0] === ' ') {
|
||||
$value = '\\20'.substr($value, 1);
|
||||
}
|
||||
if (!empty($value) && $value[strlen($value) - 1] === ' ') {
|
||||
$value = substr($value, 0, -1).'\\20';
|
||||
}
|
||||
$value = str_replace("\r", '\0d', $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function connect()
|
||||
{
|
||||
if (!$this->connection) {
|
||||
$host = $this->host;
|
||||
|
||||
if ($this->useSsl) {
|
||||
$host = 'ldaps://'.$host;
|
||||
}
|
||||
|
||||
$this->connection = ldap_connect($host, $this->port);
|
||||
|
||||
ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this->version);
|
||||
ldap_set_option($this->connection, LDAP_OPT_REFERRALS, $this->optReferrals);
|
||||
|
||||
if ($this->useStartTls) {
|
||||
ldap_start_tls($this->connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function disconnect()
|
||||
{
|
||||
if ($this->connection && is_resource($this->connection)) {
|
||||
ldap_unbind($this->connection);
|
||||
}
|
||||
|
||||
$this->connection = null;
|
||||
return $this->ldap->escape($subject, $ignore, $flags);
|
||||
}
|
||||
}
|
||||
|
@ -11,28 +11,18 @@
|
||||
|
||||
namespace Symfony\Component\Ldap;
|
||||
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
|
||||
/**
|
||||
* Ldap interface.
|
||||
*
|
||||
* This interface is used for the BC layer with branch 2.8 and 3.0.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*
|
||||
* @internal
|
||||
* @deprecated You should use LdapInterface instead
|
||||
*/
|
||||
interface LdapClientInterface
|
||||
interface LdapClientInterface extends BaseLdapInterface
|
||||
{
|
||||
/**
|
||||
* Return a connection bound to the ldap.
|
||||
*
|
||||
* @param string $dn A LDAP dn
|
||||
* @param string $password A password
|
||||
*
|
||||
* @throws ConnectionException If dn / password could not be bound.
|
||||
*/
|
||||
public function bind($dn = null, $password = null);
|
||||
|
||||
/*
|
||||
* Find a username into ldap connection.
|
||||
*
|
||||
@ -43,15 +33,4 @@ interface LdapClientInterface
|
||||
* @return array|null
|
||||
*/
|
||||
public function find($dn, $query, $filter = '*');
|
||||
|
||||
/**
|
||||
* Escape a string for use in an LDAP filter or DN.
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape($subject, $ignore = '', $flags = 0);
|
||||
}
|
||||
|
36
src/Symfony/Component/Ldap/LdapInterface.php
Normal file
36
src/Symfony/Component/Ldap/LdapInterface.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?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\Ldap;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\QueryInterface;
|
||||
|
||||
/**
|
||||
* Ldap interface.
|
||||
*
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
interface LdapInterface extends BaseLdapInterface
|
||||
{
|
||||
const ESCAPE_FILTER = 0x01;
|
||||
const ESCAPE_DN = 0x02;
|
||||
|
||||
/**
|
||||
* Queries a ldap server for entries matching the given criteria.
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $query
|
||||
* @param array $options
|
||||
*
|
||||
* @return QueryInterface
|
||||
*/
|
||||
public function query($dn, $query, array $options = array());
|
||||
}
|
@ -6,9 +6,10 @@ A Ldap client for PHP on top of PHP's ldap extension.
|
||||
Disclaimer
|
||||
----------
|
||||
|
||||
This component is currently marked as internal, as it
|
||||
still needs some work. Breaking changes will be introduced
|
||||
in the next minor version of Symfony.
|
||||
This component is only stable since Symfony 3.1. Earlier versions
|
||||
have been marked as internal as they still needed some work.
|
||||
Breaking changes were introduced in Symfony 3.1, so code relying on
|
||||
previous version of the component will break with this version.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
@ -24,4 +25,4 @@ You can run the unit tests with the following command:
|
||||
$ composer install
|
||||
$ phpunit
|
||||
|
||||
[0]: https://symfony.com/doc/2.8/components/ldap.html
|
||||
[0]: https://symfony.com/doc/3.1/components/ldap.html
|
||||
|
@ -0,0 +1,50 @@
|
||||
<?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\Ldap\Tests;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter;
|
||||
use Symfony\Component\Ldap\Adapter\ExtLdap\Collection;
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
use Symfony\Component\Ldap\LdapInterface;
|
||||
|
||||
/**
|
||||
* @requires extension ldap
|
||||
*/
|
||||
class AdapterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testLdapEscape()
|
||||
{
|
||||
$ldap = new Adapter();
|
||||
|
||||
$this->assertEquals('\20foo\3dbar\0d(baz)*\20', $ldap->escape(" foo=bar\r(baz)* ", null, LdapInterface::ESCAPE_DN));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group functional
|
||||
*/
|
||||
public function testLdapQuery()
|
||||
{
|
||||
$ldap = new Adapter(array('host' => 'localhost', 'port' => 3389));
|
||||
|
||||
$ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
|
||||
$query = $ldap->createQuery('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array());
|
||||
$result = $query->execute();
|
||||
|
||||
$this->assertInstanceOf(Collection::class, $result);
|
||||
$this->assertCount(1, $result);
|
||||
|
||||
$entry = $result[0];
|
||||
$this->assertInstanceOf(Entry::class, $entry);
|
||||
$this->assertEquals(array('Fabien Potencier'), $entry->getAttribute('cn'));
|
||||
$this->assertEquals(array('fabpot@symfony.com', 'fabien@potencier.com'), $entry->getAttribute('mail'));
|
||||
}
|
||||
}
|
17
src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf
Normal file
17
src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf
Normal file
@ -0,0 +1,17 @@
|
||||
# See slapd.conf(5) for details on configuration options.
|
||||
include /etc/ldap/schema/core.schema
|
||||
include /etc/ldap/schema/cosine.schema
|
||||
include /etc/ldap/schema/inetorgperson.schema
|
||||
include /etc/ldap/schema/nis.schema
|
||||
|
||||
pidfile /tmp/slapd/slapd.pid
|
||||
argsfile /tmp/slapd/slapd.args
|
||||
|
||||
modulepath /usr/lib/openldap
|
||||
|
||||
database ldif
|
||||
directory /tmp/slapd
|
||||
|
||||
suffix "dc=symfony,dc=com"
|
||||
rootdn "cn=admin,dc=symfony,dc=com"
|
||||
rootpw {SSHA}btWUi971ytYpVMbZLkaQ2A6ETh3VA0lL
|
4
src/Symfony/Component/Ldap/Tests/Fixtures/data/base.ldif
Normal file
4
src/Symfony/Component/Ldap/Tests/Fixtures/data/base.ldif
Normal file
@ -0,0 +1,4 @@
|
||||
dn: dc=symfony,dc=com
|
||||
objectClass: dcObject
|
||||
objectClass: organizationalUnit
|
||||
ou: Organization
|
14
src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif
Normal file
14
src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif
Normal file
@ -0,0 +1,14 @@
|
||||
dn: cn=Fabien Potencier,dc=symfony,dc=com
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Fabien Potencier
|
||||
sn: fabpot
|
||||
mail: fabpot@symfony.com
|
||||
mail: fabien@potencier.com
|
||||
ou: People
|
||||
ou: Maintainers
|
||||
ou: Founder
|
||||
givenName: Fabien Potencier
|
||||
description: Founder and project lead @Symfony
|
@ -11,18 +11,160 @@
|
||||
|
||||
namespace Symfony\Component\Ldap\Tests;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\CollectionInterface;
|
||||
use Symfony\Component\Ldap\Adapter\QueryInterface;
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
use Symfony\Component\Ldap\LdapClient;
|
||||
use Symfony\Polyfill\Php56\Php56 as p;
|
||||
use Symfony\Component\Ldap\LdapInterface;
|
||||
|
||||
/**
|
||||
* @requires extension ldap
|
||||
* @group legacy
|
||||
*/
|
||||
class LdapClientTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var LdapClient */
|
||||
private $client;
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */
|
||||
private $ldap;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->ldap = $this->getMock(LdapInterface::class);
|
||||
|
||||
$this->client = new LdapClient(null, 389, 3, false, false, false, $this->ldap);
|
||||
}
|
||||
|
||||
public function testLdapBind()
|
||||
{
|
||||
$this->ldap
|
||||
->expects($this->once())
|
||||
->method('bind')
|
||||
->with('foo', 'bar')
|
||||
;
|
||||
$this->client->bind('foo', 'bar');
|
||||
}
|
||||
|
||||
public function testLdapEscape()
|
||||
{
|
||||
$ldap = new LdapClient();
|
||||
$this->ldap
|
||||
->expects($this->once())
|
||||
->method('escape')
|
||||
->with('foo', 'bar', 'baz')
|
||||
;
|
||||
$this->client->escape('foo', 'bar', 'baz');
|
||||
}
|
||||
|
||||
$this->assertEquals('\20foo\3dbar\0d(baz)*\20', $ldap->escape(" foo=bar\r(baz)* ", null, p::LDAP_ESCAPE_DN));
|
||||
public function testLdapFind()
|
||||
{
|
||||
$collection = $this->getMock(CollectionInterface::class);
|
||||
$collection
|
||||
->expects($this->once())
|
||||
->method('getIterator')
|
||||
->will($this->returnValue(new \ArrayIterator(array(
|
||||
new Entry('cn=qux,dc=foo,dc=com', array(
|
||||
'dn' => array('cn=qux,dc=foo,dc=com'),
|
||||
'cn' => array('qux'),
|
||||
'dc' => array('com', 'foo'),
|
||||
'givenName' => array('Qux'),
|
||||
)),
|
||||
new Entry('cn=baz,dc=foo,dc=com', array(
|
||||
'dn' => array('cn=baz,dc=foo,dc=com'),
|
||||
'cn' => array('baz'),
|
||||
'dc' => array('com', 'foo'),
|
||||
'givenName' => array('Baz'),
|
||||
)),
|
||||
))))
|
||||
;
|
||||
$query = $this->getMock(QueryInterface::class);
|
||||
$query
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue($collection))
|
||||
;
|
||||
$this->ldap
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('dc=foo,dc=com', 'bar', array('filter' => 'baz'))
|
||||
->willReturn($query)
|
||||
;
|
||||
|
||||
$expected = array(
|
||||
'count' => 2,
|
||||
0 => array(
|
||||
'count' => 4,
|
||||
0 => array(
|
||||
'count' => 1,
|
||||
0 => 'cn=qux,dc=foo,dc=com',
|
||||
),
|
||||
'dn' => array(
|
||||
'count' => 1,
|
||||
0 => 'cn=qux,dc=foo,dc=com',
|
||||
),
|
||||
1 => array(
|
||||
'count' => 1,
|
||||
0 => 'qux',
|
||||
),
|
||||
'cn' => array(
|
||||
'count' => 1,
|
||||
0 => 'qux',
|
||||
),
|
||||
2 => array(
|
||||
'count' => 2,
|
||||
0 => 'com',
|
||||
1 => 'foo',
|
||||
),
|
||||
'dc' => array(
|
||||
'count' => 2,
|
||||
0 => 'com',
|
||||
1 => 'foo',
|
||||
),
|
||||
3 => array(
|
||||
'count' => 1,
|
||||
0 => 'Qux',
|
||||
),
|
||||
'givenName' => array(
|
||||
'count' => 1,
|
||||
0 => 'Qux',
|
||||
),
|
||||
),
|
||||
1 => array(
|
||||
'count' => 4,
|
||||
0 => array(
|
||||
'count' => 1,
|
||||
0 => 'cn=baz,dc=foo,dc=com',
|
||||
),
|
||||
'dn' => array(
|
||||
'count' => 1,
|
||||
0 => 'cn=baz,dc=foo,dc=com',
|
||||
),
|
||||
1 => array(
|
||||
'count' => 1,
|
||||
0 => 'baz',
|
||||
),
|
||||
'cn' => array(
|
||||
'count' => 1,
|
||||
0 => 'baz',
|
||||
),
|
||||
2 => array(
|
||||
'count' => 2,
|
||||
0 => 'com',
|
||||
1 => 'foo',
|
||||
),
|
||||
'dc' => array(
|
||||
'count' => 2,
|
||||
0 => 'com',
|
||||
1 => 'foo',
|
||||
),
|
||||
3 => array(
|
||||
'count' => 1,
|
||||
0 => 'Baz',
|
||||
),
|
||||
'givenName' => array(
|
||||
'count' => 1,
|
||||
0 => 'Baz',
|
||||
),
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expected, $this->client->find('dc=foo,dc=com', 'bar', 'baz'));
|
||||
}
|
||||
}
|
||||
|
83
src/Symfony/Component/Ldap/Tests/LdapTest.php
Normal file
83
src/Symfony/Component/Ldap/Tests/LdapTest.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?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\Ldap\Tests;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\AdapterInterface;
|
||||
use Symfony\Component\Ldap\Adapter\ConnectionInterface;
|
||||
use Symfony\Component\Ldap\Exception\DriverNotFoundException;
|
||||
use Symfony\Component\Ldap\Ldap;
|
||||
|
||||
class LdapTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */
|
||||
private $adapter;
|
||||
|
||||
/** @var Ldap */
|
||||
private $ldap;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->adapter = $this->getMock(AdapterInterface::class);
|
||||
$this->ldap = new Ldap($this->adapter);
|
||||
}
|
||||
|
||||
public function testLdapBind()
|
||||
{
|
||||
$connection = $this->getMock(ConnectionInterface::class);
|
||||
$connection
|
||||
->expects($this->once())
|
||||
->method('bind')
|
||||
->with('foo', 'bar')
|
||||
;
|
||||
$this->adapter
|
||||
->expects($this->once())
|
||||
->method('getConnection')
|
||||
->will($this->returnValue($connection))
|
||||
;
|
||||
$this->ldap->bind('foo', 'bar');
|
||||
}
|
||||
|
||||
public function testLdapEscape()
|
||||
{
|
||||
$this->adapter
|
||||
->expects($this->once())
|
||||
->method('escape')
|
||||
->with('foo', 'bar', 'baz')
|
||||
;
|
||||
$this->ldap->escape('foo', 'bar', 'baz');
|
||||
}
|
||||
|
||||
public function testLdapQuery()
|
||||
{
|
||||
$this->adapter
|
||||
->expects($this->once())
|
||||
->method('createQuery')
|
||||
->with('foo', 'bar', array('baz'))
|
||||
;
|
||||
$this->ldap->query('foo', 'bar', array('baz'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension ldap
|
||||
*/
|
||||
public function testLdapCreate()
|
||||
{
|
||||
$ldap = Ldap::create('ext_ldap');
|
||||
$this->assertInstanceOf(Ldap::class, $ldap);
|
||||
}
|
||||
|
||||
public function testCreateWithInvalidAdapterName()
|
||||
{
|
||||
$this->setExpectedException(DriverNotFoundException::class);
|
||||
Ldap::create('foo');
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"symfony/polyfill-php56": "~1.0",
|
||||
"symfony/options-resolver": "~2.8|~3.0",
|
||||
"ext-ldap": "*"
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -17,7 +17,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserCheckerInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Ldap\LdapClientInterface;
|
||||
use Symfony\Component\Ldap\LdapInterface;
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
|
||||
/**
|
||||
@ -40,11 +40,11 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
|
||||
* @param UserProviderInterface $userProvider A UserProvider
|
||||
* @param UserCheckerInterface $userChecker A UserChecker
|
||||
* @param string $providerKey The provider key
|
||||
* @param LdapClientInterface $ldap An Ldap client
|
||||
* @param LdapInterface $ldap A Ldap client
|
||||
* @param string $dnString A string used to create the bind DN
|
||||
* @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not
|
||||
*/
|
||||
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, LdapClientInterface $ldap, $dnString = '{username}', $hideUserNotFoundExceptions = true)
|
||||
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, LdapInterface $ldap, $dnString = '{username}', $hideUserNotFoundExceptions = true)
|
||||
{
|
||||
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
|
||||
|
||||
@ -74,7 +74,7 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
|
||||
$password = $token->getCredentials();
|
||||
|
||||
try {
|
||||
$username = $this->ldap->escape($username, '', LDAP_ESCAPE_DN);
|
||||
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN);
|
||||
$dn = str_replace('{username}', $username, $this->dnString);
|
||||
|
||||
$this->ldap->bind($dn, $password);
|
||||
|
@ -11,10 +11,13 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
|
||||
|
||||
use Symfony\Component\Ldap\LdapInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Provider\LdapBindAuthenticationProvider;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
use Symfony\Component\Security\Core\User\UserCheckerInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
/**
|
||||
* @requires extension ldap
|
||||
@ -27,14 +30,14 @@ class LdapBindAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testBindFailureShouldThrowAnException()
|
||||
{
|
||||
$userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
|
||||
$ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface');
|
||||
$userProvider = $this->getMock(UserProviderInterface::class);
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
$ldap
|
||||
->expects($this->once())
|
||||
->method('bind')
|
||||
->will($this->throwException(new ConnectionException()))
|
||||
;
|
||||
$userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
|
||||
$userChecker = $this->getMock(UserCheckerInterface::class);
|
||||
|
||||
$provider = new LdapBindAuthenticationProvider($userProvider, $userChecker, 'key', $ldap);
|
||||
$reflection = new \ReflectionMethod($provider, 'checkAuthentication');
|
||||
@ -45,15 +48,15 @@ class LdapBindAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testRetrieveUser()
|
||||
{
|
||||
$userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
|
||||
$userProvider = $this->getMock(UserProviderInterface::class);
|
||||
$userProvider
|
||||
->expects($this->once())
|
||||
->method('loadUserByUsername')
|
||||
->with('foo')
|
||||
;
|
||||
$ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface');
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
|
||||
$userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
|
||||
$userChecker = $this->getMock(UserCheckerInterface::class);
|
||||
|
||||
$provider = new LdapBindAuthenticationProvider($userProvider, $userChecker, 'key', $ldap);
|
||||
$reflection = new \ReflectionMethod($provider, 'retrieveUser');
|
||||
|
@ -11,6 +11,10 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\Tests\User;
|
||||
|
||||
use Symfony\Component\Ldap\Adapter\CollectionInterface;
|
||||
use Symfony\Component\Ldap\Adapter\QueryInterface;
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
use Symfony\Component\Ldap\LdapInterface;
|
||||
use Symfony\Component\Security\Core\User\LdapUserProvider;
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
|
||||
@ -24,7 +28,7 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testLoadUserByUsernameFailsIfCantConnectToLdap()
|
||||
{
|
||||
$ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface');
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
$ldap
|
||||
->expects($this->once())
|
||||
->method('bind')
|
||||
@ -40,12 +44,29 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testLoadUserByUsernameFailsIfNoLdapEntries()
|
||||
{
|
||||
$ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface');
|
||||
$result = $this->getMock(CollectionInterface::class);
|
||||
$query = $this->getMock(QueryInterface::class);
|
||||
$query
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue($result))
|
||||
;
|
||||
$result
|
||||
->expects($this->once())
|
||||
->method('count')
|
||||
->will($this->returnValue(0))
|
||||
;
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
$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');
|
||||
$provider->loadUserByUsername('foo');
|
||||
@ -56,7 +77,19 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testLoadUserByUsernameFailsIfMoreThanOneLdapEntry()
|
||||
{
|
||||
$ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface');
|
||||
$result = $this->getMock(CollectionInterface::class);
|
||||
$query = $this->getMock(QueryInterface::class);
|
||||
$query
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue($result))
|
||||
;
|
||||
$result
|
||||
->expects($this->once())
|
||||
->method('count')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
$ldap
|
||||
->expects($this->once())
|
||||
->method('escape')
|
||||
@ -64,12 +97,8 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
;
|
||||
$ldap
|
||||
->expects($this->once())
|
||||
->method('find')
|
||||
->will($this->returnValue(array(
|
||||
array(),
|
||||
array(),
|
||||
'count' => 2,
|
||||
)))
|
||||
->method('query')
|
||||
->will($this->returnValue($query))
|
||||
;
|
||||
|
||||
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
|
||||
@ -78,7 +107,29 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testSuccessfulLoadUserByUsername()
|
||||
{
|
||||
$ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface');
|
||||
$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' => 'foo',
|
||||
'userpassword' => 'bar',
|
||||
)
|
||||
)))
|
||||
;
|
||||
$result
|
||||
->expects($this->once())
|
||||
->method('count')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
$ldap
|
||||
->expects($this->once())
|
||||
->method('escape')
|
||||
@ -86,14 +137,8 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
;
|
||||
$ldap
|
||||
->expects($this->once())
|
||||
->method('find')
|
||||
->will($this->returnValue(array(
|
||||
array(
|
||||
'sAMAccountName' => 'foo',
|
||||
'userpassword' => 'bar',
|
||||
),
|
||||
'count' => 1,
|
||||
)))
|
||||
->method('query')
|
||||
->will($this->returnValue($query))
|
||||
;
|
||||
|
||||
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
|
||||
|
@ -11,10 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\User;
|
||||
|
||||
use Symfony\Component\Ldap\Entry;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Ldap\Exception\ConnectionException;
|
||||
use Symfony\Component\Ldap\LdapClientInterface;
|
||||
use Symfony\Component\Ldap\LdapInterface;
|
||||
|
||||
/**
|
||||
* LdapUserProvider is a simple user provider on top of ldap.
|
||||
@ -32,15 +33,15 @@ class LdapUserProvider implements UserProviderInterface
|
||||
private $defaultSearch;
|
||||
|
||||
/**
|
||||
* @param LdapClientInterface $ldap
|
||||
* @param string $baseDn
|
||||
* @param string $searchDn
|
||||
* @param string $searchPassword
|
||||
* @param array $defaultRoles
|
||||
* @param string $uidKey
|
||||
* @param string $filter
|
||||
* @param LdapInterface $ldap
|
||||
* @param string $baseDn
|
||||
* @param string $searchDn
|
||||
* @param string $searchPassword
|
||||
* @param array $defaultRoles
|
||||
* @param string $uidKey
|
||||
* @param string $filter
|
||||
*/
|
||||
public function __construct(LdapClientInterface $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})')
|
||||
{
|
||||
$this->ldap = $ldap;
|
||||
$this->baseDn = $baseDn;
|
||||
@ -57,33 +58,25 @@ class LdapUserProvider implements UserProviderInterface
|
||||
{
|
||||
try {
|
||||
$this->ldap->bind($this->searchDn, $this->searchPassword);
|
||||
$username = $this->ldap->escape($username, '', LDAP_ESCAPE_FILTER);
|
||||
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
|
||||
$query = str_replace('{username}', $username, $this->defaultSearch);
|
||||
$search = $this->ldap->find($this->baseDn, $query);
|
||||
$search = $this->ldap->query($this->baseDn, $query);
|
||||
} catch (ConnectionException $e) {
|
||||
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e);
|
||||
}
|
||||
|
||||
if (!$search) {
|
||||
$entries = $search->execute();
|
||||
$count = count($entries);
|
||||
|
||||
if (!$count) {
|
||||
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
|
||||
}
|
||||
|
||||
if ($search['count'] > 1) {
|
||||
if ($count > 1) {
|
||||
throw new UsernameNotFoundException('More than one user found');
|
||||
}
|
||||
|
||||
$user = $search[0];
|
||||
|
||||
return $this->loadUser($username, $user);
|
||||
}
|
||||
|
||||
public function loadUser($username, $user)
|
||||
{
|
||||
$password = isset($user['userpassword']) ? $user['userpassword'] : null;
|
||||
|
||||
$roles = $this->defaultRoles;
|
||||
|
||||
return new User($username, $password, $roles);
|
||||
return $this->loadUser($username, $entries[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,4 +98,9 @@ class LdapUserProvider implements UserProviderInterface
|
||||
{
|
||||
return $class === 'Symfony\Component\Security\Core\User\User';
|
||||
}
|
||||
|
||||
private function loadUser($username, Entry $entry)
|
||||
{
|
||||
return new User($username, $entry->getAttribute('userpassword'), $this->defaultRoles);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||
"symfony/expression-language": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~2.8|~3.0",
|
||||
"symfony/ldap": "~2.8|~3.0.0",
|
||||
"symfony/ldap": "~3.1",
|
||||
"symfony/validator": "~2.8|~3.0",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
|
@ -37,7 +37,7 @@
|
||||
"symfony/routing": "~2.8|~3.0",
|
||||
"symfony/validator": "~2.8|~3.0",
|
||||
"symfony/expression-language": "~2.8|~3.0",
|
||||
"symfony/ldap": "~2.8|~3.0.0",
|
||||
"symfony/ldap": "~3.1",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
Reference in New Issue
Block a user